ddnet/src/game/gamecore.h

316 lines
6.2 KiB
C
Raw Normal View History

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/system.h>
#include <base/math.h>
2013-07-18 22:27:17 +00:00
#include <map>
#include <vector>
2010-05-29 07:25:38 +00:00
#include <math.h>
#include "collision.h"
#include <engine/shared/protocol.h>
#include <game/generated/protocol.h>
2020-05-25 13:08:24 +00:00
#include "prng.h"
#include "teamscore.h"
#include "mapitems.h"
2010-05-29 07:25:38 +00:00
2011-01-06 03:46:10 +00:00
2010-05-29 07:25:38 +00:00
class CTuneParam
{
int m_Value;
public:
void Set(int v) { m_Value = v; }
int Get() const { return m_Value; }
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; }
};
class CTuningParams
{
public:
CTuningParams()
{
const float TicksPerSecond = 50.0f;
2015-03-29 01:52:33 +00:00
#define MACRO_TUNING_PARAM(Name,ScriptName,Value,Description) m_##Name.Set((int)(Value*100.0f));
2010-05-29 07:25:38 +00:00
#include "tuning.h"
#undef MACRO_TUNING_PARAM
}
2017-03-21 10:24:44 +00:00
static const char *ms_apNames[];
2015-03-29 01:52:33 +00:00
#define MACRO_TUNING_PARAM(Name,ScriptName,Value,Description) CTuneParam m_##Name;
2010-05-29 07:25:38 +00:00
#include "tuning.h"
#undef MACRO_TUNING_PARAM
2010-05-29 07:25:38 +00:00
static int Num() { return sizeof(CTuningParams)/sizeof(int); }
bool Set(int Index, float Value);
bool Set(const char *pName, float Value);
bool Get(int Index, float *pValue);
bool Get(const char *pName, float *pValue);
};
inline vec2 GetDirection(int Angle)
{
float a = Angle/256.0f;
return vec2(cosf(a), sinf(a));
}
inline vec2 GetDir(float Angle)
2010-05-29 07:25:38 +00:00
{
return vec2(cosf(Angle), sinf(Angle));
2010-05-29 07:25:38 +00:00
}
inline float GetAngle(vec2 Dir)
{
if(Dir.x == 0 && Dir.y == 0)
2010-05-29 07:25:38 +00:00
return 0.0f;
float a = atanf(Dir.y/Dir.x);
2010-05-29 07:25:38 +00:00
if(Dir.x < 0)
a = a+pi;
return a;
2010-05-29 07:25:38 +00:00
}
inline void StrToInts(int *pInts, int Num, const char *pStr)
{
int Index = 0;
while(Num)
{
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
2010-05-29 07:25:38 +00:00
*pInts = ((aBuf[0]+128)<<24)|((aBuf[1]+128)<<16)|((aBuf[2]+128)<<8)|(aBuf[3]+128);
pInts++;
Num--;
}
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)
{
pStr[0] = (((*pInts)>>24)&0xff)-128;
pStr[1] = (((*pInts)>>16)&0xff)-128;
pStr[2] = (((*pInts)>>8)&0xff)-128;
pStr[3] = ((*pInts)&0xff)-128;
pStr += 4;
pInts++;
Num--;
}
#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;
#if defined(__GNUC__) && __GNUC__ >= 7
#pragma GCC diagnostic pop
#endif
2010-05-29 07:25:38 +00:00
}
inline vec2 CalcPos(vec2 Pos, vec2 Velocity, float Curvature, float Speed, float Time)
2010-05-29 07:25:38 +00:00
{
vec2 n;
Time *= Speed;
n.x = Pos.x + Velocity.x*Time;
n.y = Pos.y + Velocity.y*Time + Curvature/10000*(Time*Time);
return n;
2010-05-29 07:25:38 +00:00
}
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)
return Current;
2010-05-29 07:25:38 +00:00
Current += Modifier;
if(Current < Min)
Current = Min;
return Current;
2010-05-29 07:25:38 +00:00
}
else
{
if(Current > Max)
return Current;
2010-05-29 07:25:38 +00:00
Current += Modifier;
if(Current > Max)
Current = Max;
return Current;
2010-05-29 07:25:38 +00:00
}
}
float VelocityRamp(float Value, float Start, float Range, float Curvature);
// hooking stuff
enum
{
HOOK_RETRACTED=-1,
HOOK_IDLE=0,
HOOK_RETRACT_START=1,
HOOK_RETRACT_END=3,
HOOK_FLYING,
HOOK_GRABBED,
2010-05-29 07:25:38 +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
};
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;
}
// 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.
return m_pPrng->RandomBits() % BelowThis;
2010-05-29 07:25:38 +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
{
friend class CCharacter;
2010-05-29 07:25:38 +00:00
CWorldCore *m_pWorld;
CCollision *m_pCollision;
std::map<int, std::vector<vec2> > *m_pTeleOuts;
2010-05-29 07:25:38 +00:00
public:
vec2 m_Pos;
vec2 m_Vel;
bool m_Hook;
bool m_Collision;
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;
2014-04-14 08:56:14 +00:00
int m_ActiveWeapon;
2013-07-18 22:27:17 +00:00
bool m_NewHook;
2010-05-29 07:25:38 +00:00
int m_Jumped;
int m_JumpedTotal;
int m_Jumps;
2010-05-29 07:25:38 +00:00
int m_Direction;
int m_Angle;
CNetObj_PlayerInput m_Input;
2010-05-29 07:25:38 +00:00
int m_TriggeredEvents;
2017-03-21 10:24:44 +00:00
void Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore *pTeams);
void Init(CWorldCore *pWorld, CCollision *pCollision, CTeamsCore *pTeams, std::map<int, std::vector<vec2> > *pTeleOuts);
2010-05-29 07:25:38 +00:00
void Reset();
void Tick(bool UseInput);
void Move();
2010-05-29 07:25:38 +00:00
void Read(const CNetObj_CharacterCore *pObjCore);
void Write(CNetObj_CharacterCore *pObjCore);
void Quantize();
// DDRace
int m_Id;
bool m_pReset;
class CCollision *Collision() { return m_pCollision; }
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;
// DDnet Character
void ReadDDNet(const CNetObj_DDNetCharacter *pObjDDNet);
2019-04-12 14:29:13 +00:00
bool m_Solo;
bool m_Jetpack;
bool m_NoCollision;
bool m_EndlessHook;
bool m_EndlessJump;
bool m_NoHammerHit;
bool m_NoGrenadeHit;
bool m_NoLaserHit;
bool m_NoShotgunHit;
bool m_NoHookHit;
bool m_Super;
bool m_HasTelegunGun;
bool m_HasTelegunGrenade;
bool m_HasTelegunLaser;
2019-04-23 16:13:07 +00:00
int m_FreezeEnd;
bool m_DeepFrozen;
2014-06-21 22:50:11 +00:00
private:
2017-03-21 10:24:44 +00:00
CTeamsCore *m_pTeams;
int m_MoveRestrictions;
static bool IsSwitchActiveCb(int Number, void *pUser);
2010-05-29 07:25:38 +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)
{
i = (i+1)&INPUT_STATE_MASK;
if(i&1)
c.m_Presses++;
else
c.m_Releases++;
}
return c;
}
#endif