2010-11-20 10:37:14 +00:00
|
|
|
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
|
|
|
|
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
2010-05-29 07:25:38 +00:00
|
|
|
#ifndef GAME_GAMECORE_H
|
|
|
|
#define GAME_GAMECORE_H
|
|
|
|
|
|
|
|
#include <base/math.h>
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <base/system.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2013-07-18 22:27:17 +00:00
|
|
|
#include <map>
|
|
|
|
#include <vector>
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
#include "collision.h"
|
|
|
|
#include <engine/shared/protocol.h>
|
|
|
|
#include <game/generated/protocol.h>
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <math.h>
|
2010-05-29 07:25:38 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
#include "mapitems.h"
|
2020-05-25 13:08:24 +00:00
|
|
|
#include "prng.h"
|
2010-08-30 12:13:43 +00:00
|
|
|
#include "teamscore.h"
|
2011-01-06 03:46:10 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
class CTuneParam
|
|
|
|
{
|
|
|
|
int m_Value;
|
2020-09-26 19:41:58 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
public:
|
|
|
|
void Set(int v) { m_Value = v; }
|
|
|
|
int Get() const { return m_Value; }
|
2020-09-26 19:41:58 +00:00
|
|
|
CTuneParam &operator=(int v)
|
|
|
|
{
|
|
|
|
m_Value = (int)(v * 100.0f);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
CTuneParam &operator=(float v)
|
|
|
|
{
|
|
|
|
m_Value = (int)(v * 100.0f);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
operator float() const { return m_Value / 100.0f; }
|
2010-05-29 07:25:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class CTuningParams
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CTuningParams()
|
|
|
|
{
|
|
|
|
const float TicksPerSecond = 50.0f;
|
2020-09-26 19:41:58 +00:00
|
|
|
#define MACRO_TUNING_PARAM(Name, ScriptName, Value, Description) m_##Name.Set((int)(Value * 100.0f));
|
|
|
|
#include "tuning.h"
|
|
|
|
#undef MACRO_TUNING_PARAM
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2017-03-21 10:24:44 +00:00
|
|
|
static const char *ms_apNames[];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
#define MACRO_TUNING_PARAM(Name, ScriptName, Value, Description) CTuneParam m_##Name;
|
|
|
|
#include "tuning.h"
|
|
|
|
#undef MACRO_TUNING_PARAM
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
static int Num()
|
|
|
|
{
|
|
|
|
return sizeof(CTuningParams) / sizeof(int);
|
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
bool Set(int Index, float Value);
|
|
|
|
bool Set(const char *pName, float Value);
|
2021-02-08 21:26:26 +00:00
|
|
|
bool Get(int Index, float *pValue) const;
|
|
|
|
bool Get(const char *pName, float *pValue) const;
|
2010-05-29 07:25:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
inline void StrToInts(int *pInts, int Num, const char *pStr)
|
|
|
|
{
|
|
|
|
int Index = 0;
|
|
|
|
while(Num)
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
char aBuf[4] = {0, 0, 0, 0};
|
2019-10-16 12:33:58 +00:00
|
|
|
#ifdef __GNUC__
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Warray-bounds" // false positive
|
|
|
|
#endif
|
2010-05-29 07:25:38 +00:00
|
|
|
for(int c = 0; c < 4 && pStr[Index]; c++, Index++)
|
|
|
|
aBuf[c] = pStr[Index];
|
2019-10-16 12:33:58 +00:00
|
|
|
#ifdef __GNUC__
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
#endif
|
2020-09-26 19:41:58 +00:00
|
|
|
*pInts = ((aBuf[0] + 128) << 24) | ((aBuf[1] + 128) << 16) | ((aBuf[2] + 128) << 8) | (aBuf[3] + 128);
|
2010-05-29 07:25:38 +00:00
|
|
|
pInts++;
|
|
|
|
Num--;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
// null terminate
|
|
|
|
pInts[-1] &= 0xffffff00;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void IntsToStr(const int *pInts, int Num, char *pStr)
|
|
|
|
{
|
|
|
|
while(Num)
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
pStr[0] = (((*pInts) >> 24) & 0xff) - 128;
|
|
|
|
pStr[1] = (((*pInts) >> 16) & 0xff) - 128;
|
|
|
|
pStr[2] = (((*pInts) >> 8) & 0xff) - 128;
|
|
|
|
pStr[3] = ((*pInts) & 0xff) - 128;
|
2010-05-29 07:25:38 +00:00
|
|
|
pStr += 4;
|
|
|
|
pInts++;
|
|
|
|
Num--;
|
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-06-23 06:09:46 +00:00
|
|
|
#if defined(__GNUC__) && __GNUC__ >= 7
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wstringop-overflow" // false positive
|
|
|
|
#endif
|
2010-05-29 07:25:38 +00:00
|
|
|
// null terminate
|
|
|
|
pStr[-1] = 0;
|
2020-06-23 06:09:46 +00:00
|
|
|
#if defined(__GNUC__) && __GNUC__ >= 7
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
#endif
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
2011-02-13 06:47:51 +00:00
|
|
|
inline vec2 CalcPos(vec2 Pos, vec2 Velocity, float Curvature, float Speed, float Time)
|
2010-05-29 07:25:38 +00:00
|
|
|
{
|
2011-02-13 06:47:51 +00:00
|
|
|
vec2 n;
|
|
|
|
Time *= Speed;
|
2020-09-26 19:41:58 +00:00
|
|
|
n.x = Pos.x + Velocity.x * Time;
|
|
|
|
n.y = Pos.y + Velocity.y * Time + Curvature / 10000 * (Time * Time);
|
2011-02-13 06:47:51 +00:00
|
|
|
return n;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline T SaturatedAdd(T Min, T Max, T Current, T Modifier)
|
|
|
|
{
|
|
|
|
if(Modifier < 0)
|
|
|
|
{
|
|
|
|
if(Current < Min)
|
2014-05-01 01:03:31 +00:00
|
|
|
return Current;
|
2010-05-29 07:25:38 +00:00
|
|
|
Current += Modifier;
|
|
|
|
if(Current < Min)
|
|
|
|
Current = Min;
|
2014-05-01 01:03:31 +00:00
|
|
|
return Current;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(Current > Max)
|
2014-05-01 01:03:31 +00:00
|
|
|
return Current;
|
2010-05-29 07:25:38 +00:00
|
|
|
Current += Modifier;
|
|
|
|
if(Current > Max)
|
|
|
|
Current = Max;
|
2014-05-01 01:03:31 +00:00
|
|
|
return Current;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float VelocityRamp(float Value, float Start, float Range, float Curvature);
|
|
|
|
|
|
|
|
// hooking stuff
|
|
|
|
enum
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
HOOK_RETRACTED = -1,
|
|
|
|
HOOK_IDLE = 0,
|
|
|
|
HOOK_RETRACT_START = 1,
|
|
|
|
HOOK_RETRACT_END = 3,
|
2010-05-29 07:25:38 +00:00
|
|
|
HOOK_FLYING,
|
|
|
|
HOOK_GRABBED,
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
COREEVENT_GROUND_JUMP = 0x01,
|
|
|
|
COREEVENT_AIR_JUMP = 0x02,
|
|
|
|
COREEVENT_HOOK_LAUNCH = 0x04,
|
|
|
|
COREEVENT_HOOK_ATTACH_PLAYER = 0x08,
|
|
|
|
COREEVENT_HOOK_ATTACH_GROUND = 0x10,
|
|
|
|
COREEVENT_HOOK_HIT_NOHOOK = 0x20,
|
|
|
|
COREEVENT_HOOK_RETRACT = 0x40,
|
2013-07-18 22:27:17 +00:00
|
|
|
//COREEVENT_HOOK_TELE=0x80,
|
2010-05-29 07:25:38 +00:00
|
|
|
};
|
|
|
|
|
2022-03-03 21:56:32 +00:00
|
|
|
// show others values - do not change them
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
SHOW_OTHERS_NOT_SET = -1, // show others value before it is set
|
|
|
|
SHOW_OTHERS_OFF = 0, // show no other players in solo or other teams
|
|
|
|
SHOW_OTHERS_ON = 1, // show all other players in solo and other teams
|
|
|
|
SHOW_OTHERS_ONLY_TEAM = 2 // show players that are in solo and are in the same team
|
|
|
|
};
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
class CWorldCore
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CWorldCore()
|
|
|
|
{
|
|
|
|
mem_zero(m_apCharacters, sizeof(m_apCharacters));
|
2020-05-25 13:08:24 +00:00
|
|
|
m_pPrng = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int RandomOr0(int BelowThis)
|
|
|
|
{
|
|
|
|
if(BelowThis <= 1 || !m_pPrng)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
2020-05-27 16:12:42 +00:00
|
|
|
// This makes the random number slightly biased if `BelowThis`
|
|
|
|
// is not a power of two, but we have decided that this is not
|
|
|
|
// significant for DDNet and favored the simple implementation.
|
2020-05-26 08:59:49 +00:00
|
|
|
return m_pPrng->RandomBits() % BelowThis;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2014-04-29 01:34:23 +00:00
|
|
|
CTuningParams m_Tuning[2];
|
2010-05-29 07:25:38 +00:00
|
|
|
class CCharacterCore *m_apCharacters[MAX_CLIENTS];
|
2020-05-25 13:08:24 +00:00
|
|
|
CPrng *m_pPrng;
|
2010-05-29 07:25:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class CCharacterCore
|
|
|
|
{
|
2014-03-13 00:03:39 +00:00
|
|
|
friend class CCharacter;
|
2010-05-29 07:25:38 +00:00
|
|
|
CWorldCore *m_pWorld;
|
|
|
|
CCollision *m_pCollision;
|
2020-09-26 19:41:58 +00:00
|
|
|
std::map<int, std::vector<vec2>> *m_pTeleOuts;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
public:
|
|
|
|
vec2 m_Pos;
|
|
|
|
vec2 m_Vel;
|
2013-08-05 15:47:04 +00:00
|
|
|
bool m_Hook;
|
|
|
|
bool m_Collision;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 m_HookPos;
|
|
|
|
vec2 m_HookDir;
|
2013-07-18 22:27:17 +00:00
|
|
|
vec2 m_HookTeleBase;
|
2010-05-29 07:25:38 +00:00
|
|
|
int m_HookTick;
|
|
|
|
int m_HookState;
|
|
|
|
int m_HookedPlayer;
|
2022-03-21 22:50:41 +00:00
|
|
|
|
2014-04-14 08:56:14 +00:00
|
|
|
int m_ActiveWeapon;
|
2022-03-21 22:50:41 +00:00
|
|
|
struct WeaponStat
|
|
|
|
{
|
|
|
|
int m_AmmoRegenStart;
|
|
|
|
int m_Ammo;
|
|
|
|
int m_Ammocost;
|
|
|
|
bool m_Got;
|
|
|
|
} m_aWeapons[NUM_WEAPONS];
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-03-24 00:05:41 +00:00
|
|
|
// ninja
|
|
|
|
struct
|
|
|
|
{
|
|
|
|
vec2 m_ActivationDir;
|
|
|
|
int m_ActivationTick;
|
|
|
|
int m_CurrentMoveTime;
|
|
|
|
int m_OldVelAmount;
|
|
|
|
} m_Ninja;
|
|
|
|
|
2013-07-18 22:27:17 +00:00
|
|
|
bool m_NewHook;
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int m_Jumped;
|
2022-05-16 21:17:19 +00:00
|
|
|
// m_JumpedTotal counts the jumps performed in the air
|
2013-08-23 23:03:45 +00:00
|
|
|
int m_JumpedTotal;
|
|
|
|
int m_Jumps;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int m_Direction;
|
|
|
|
int m_Angle;
|
|
|
|
CNetObj_PlayerInput m_Input;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int m_TriggeredEvents;
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2021-01-12 23:25:26 +00:00
|
|
|
void Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore *pTeams = nullptr, std::map<int, std::vector<vec2>> *pTeleOuts = nullptr);
|
2010-05-29 07:25:38 +00:00
|
|
|
void Reset();
|
2019-04-11 22:46:54 +00:00
|
|
|
void Tick(bool UseInput);
|
2018-08-22 06:33:21 +00:00
|
|
|
void Move();
|
2011-04-13 18:37:12 +00:00
|
|
|
|
2022-03-23 17:19:23 +00:00
|
|
|
void ReadCharacterCore(const CNetObj_CharacterCore *pObjCore);
|
2022-03-24 09:17:35 +00:00
|
|
|
void ReadCharacter(const CNetObj_Character *pObjChar);
|
2010-05-29 07:25:38 +00:00
|
|
|
void Write(CNetObj_CharacterCore *pObjCore);
|
|
|
|
void Quantize();
|
2011-04-09 06:41:31 +00:00
|
|
|
|
|
|
|
// DDRace
|
|
|
|
|
|
|
|
int m_Id;
|
|
|
|
bool m_pReset;
|
|
|
|
class CCollision *Collision() { return m_pCollision; }
|
2010-09-08 16:22:11 +00:00
|
|
|
|
2014-06-21 22:50:11 +00:00
|
|
|
vec2 m_LastVel;
|
|
|
|
int m_Colliding;
|
2014-06-23 12:46:27 +00:00
|
|
|
bool m_LeftWall;
|
2019-04-19 09:17:28 +00:00
|
|
|
|
2021-01-31 19:29:41 +00:00
|
|
|
// DDNet Character
|
2021-01-12 23:29:20 +00:00
|
|
|
void SetTeamsCore(CTeamsCore *pTeams);
|
2021-01-12 23:12:08 +00:00
|
|
|
void SetTeleOuts(std::map<int, std::vector<vec2>> *pTeleOuts);
|
2019-06-30 21:47:33 +00:00
|
|
|
void ReadDDNet(const CNetObj_DDNetCharacter *pObjDDNet);
|
2022-03-27 16:18:53 +00:00
|
|
|
void ReadDDNetDisplayInfo(const CNetObj_DDNetCharacterDisplayInfo *pObjDDNet);
|
2019-04-12 14:29:13 +00:00
|
|
|
bool m_Solo;
|
2019-04-19 09:17:28 +00:00
|
|
|
bool m_Jetpack;
|
|
|
|
bool m_NoCollision;
|
|
|
|
bool m_EndlessHook;
|
|
|
|
bool m_EndlessJump;
|
|
|
|
bool m_NoHammerHit;
|
|
|
|
bool m_NoGrenadeHit;
|
2019-11-22 14:37:18 +00:00
|
|
|
bool m_NoLaserHit;
|
2019-04-19 09:17:28 +00:00
|
|
|
bool m_NoShotgunHit;
|
|
|
|
bool m_NoHookHit;
|
|
|
|
bool m_Super;
|
|
|
|
bool m_HasTelegunGun;
|
|
|
|
bool m_HasTelegunGrenade;
|
|
|
|
bool m_HasTelegunLaser;
|
2022-03-25 11:54:11 +00:00
|
|
|
int m_FreezeTick;
|
2019-04-23 16:13:07 +00:00
|
|
|
int m_FreezeEnd;
|
2022-03-27 16:18:53 +00:00
|
|
|
bool m_IsInFreeze;
|
2019-04-19 09:17:28 +00:00
|
|
|
bool m_DeepFrozen;
|
2022-01-07 15:53:40 +00:00
|
|
|
bool m_LiveFrozen;
|
2021-05-12 16:57:50 +00:00
|
|
|
CTuningParams m_Tuning;
|
2014-06-21 22:50:11 +00:00
|
|
|
|
2011-04-09 06:41:31 +00:00
|
|
|
private:
|
2017-03-21 10:24:44 +00:00
|
|
|
CTeamsCore *m_pTeams;
|
2018-08-15 15:47:07 +00:00
|
|
|
int m_MoveRestrictions;
|
|
|
|
static bool IsSwitchActiveCb(int Number, void *pUser);
|
2010-05-29 07:25:38 +00:00
|
|
|
};
|
|
|
|
|
2014-12-01 00:31:58 +00:00
|
|
|
//input count
|
|
|
|
struct CInputCount
|
|
|
|
{
|
|
|
|
int m_Presses;
|
|
|
|
int m_Releases;
|
|
|
|
};
|
|
|
|
|
|
|
|
inline CInputCount CountInput(int Prev, int Cur)
|
|
|
|
{
|
|
|
|
CInputCount c = {0, 0};
|
|
|
|
Prev &= INPUT_STATE_MASK;
|
|
|
|
Cur &= INPUT_STATE_MASK;
|
|
|
|
int i = Prev;
|
|
|
|
|
|
|
|
while(i != Cur)
|
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
i = (i + 1) & INPUT_STATE_MASK;
|
|
|
|
if(i & 1)
|
2014-12-01 00:31:58 +00:00
|
|
|
c.m_Presses++;
|
|
|
|
else
|
|
|
|
c.m_Releases++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2011-08-13 00:11:06 +00:00
|
|
|
#endif
|