mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Merge #6560
6560: Replace EntityEx with new netobjs r=edg-l a=trml This is a proposal for replacing EntityEx with new netobjects, like suggested in #5860. - Adds a new DDNetPickup that includes switch number - a new DDNetProjectile that replaces the old one (which is renamed to DDRaceProjectile) - includes switch number, tunezone and velocity/speed (plus a flag that can be used to send velocitiy of player projectiles with full precision) - switch number and subtype is added to DDNetLaser (to distinguish e.g. draggers with different strength) The pr removes EntityEx from the server, but keeps compatibility in the client. <!-- What is the motivation for the changes of this pull request? --> <!-- Note that builds and other checks will be run for your change. Don't feel intimidated by failures in some of the checks. If you can't resolve them yourself, experienced devs can also resolve them before merging your pull request. --> ## Checklist - [ ] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: trml <trml@users.noreply.github.com>
This commit is contained in:
commit
e9d08a15fd
|
@ -2256,6 +2256,8 @@ if(CLIENT)
|
|||
laser_data.h
|
||||
lineinput.cpp
|
||||
lineinput.h
|
||||
pickup_data.cpp
|
||||
pickup_data.h
|
||||
prediction/entities/character.cpp
|
||||
prediction/entities/character.h
|
||||
prediction/entities/laser.cpp
|
||||
|
|
|
@ -29,12 +29,17 @@ GameInfoFlags2 = [
|
|||
"HUD_DDRACE", "NO_WEAK_HOOK"
|
||||
]
|
||||
ExPlayerFlags = ["AFK", "PAUSED", "SPEC"]
|
||||
ProjectileFlags = [f"CLIENTID_BIT{i}" for i in range(8)] + [
|
||||
LegacyProjectileFlags = [f"CLIENTID_BIT{i}" for i in range(8)] + [
|
||||
"NO_OWNER", "IS_DDNET", "BOUNCE_HORIZONTAL", "BOUNCE_VERTICAL",
|
||||
"EXPLOSIVE", "FREEZE",
|
||||
]
|
||||
ProjectileFlags = [
|
||||
"BOUNCE_HORIZONTAL", "BOUNCE_VERTICAL", "EXPLOSIVE", "FREEZE", "NORMALIZE_VEL",
|
||||
]
|
||||
|
||||
LaserTypes = ["RIFLE", "SHOTGUN", "DOOR", "FREEZE"]
|
||||
LaserTypes = ["RIFLE", "SHOTGUN", "DOOR", "FREEZE", "DRAGGER", "GUN", "PLASMA"]
|
||||
DraggerTypes = ["WEAK", "WEAK_NW", "NORMAL", "NORMAL_NW", "STRONG", "STRONG_NW"]
|
||||
GunTypes = ["UNFREEZE", "EXPLOSIVE", "FREEZE", "EXPFREEZE"]
|
||||
|
||||
Emoticons = ["OOP", "EXCLAMATION", "HEARTS", "DROP", "DOTDOT", "MUSIC", "SORRY", "GHOST", "SUSHI", "SPLATTEE", "DEVILTEE", "ZOMG", "ZZZ", "WTF", "EYES", "QUESTION"]
|
||||
|
||||
|
@ -81,6 +86,8 @@ Enums = [
|
|||
Enum("AUTHED", Authed),
|
||||
Enum("ENTITYCLASS", EntityClasses),
|
||||
Enum("LASERTYPE", LaserTypes),
|
||||
Enum("LASERDRAGGERTYPE", DraggerTypes),
|
||||
Enum("LASERGUNTYPE", GunTypes),
|
||||
]
|
||||
|
||||
Flags = [
|
||||
|
@ -91,6 +98,7 @@ Flags = [
|
|||
Flags("GAMEINFOFLAG", GameInfoFlags),
|
||||
Flags("GAMEINFOFLAG2", GameInfoFlags2),
|
||||
Flags("EXPLAYERFLAG", ExPlayerFlags),
|
||||
Flags("LEGACYPROJECTILEFLAG", LegacyProjectileFlags),
|
||||
Flags("PROJECTILEFLAG", ProjectileFlags),
|
||||
]
|
||||
|
||||
|
@ -267,7 +275,7 @@ Objects = [
|
|||
|
||||
# The code assumes that this has the same in-memory representation as
|
||||
# the Projectile net object.
|
||||
NetObjectEx("DDNetProjectile", "projectile@netobj.ddnet.tw", [
|
||||
NetObjectEx("DDRaceProjectile", "projectile@netobj.ddnet.tw", [
|
||||
NetIntAny("m_X"),
|
||||
NetIntAny("m_Y"),
|
||||
NetIntAny("m_Angle"),
|
||||
|
@ -284,6 +292,29 @@ Objects = [
|
|||
NetTick("m_StartTick"),
|
||||
NetIntRange("m_Owner", -1, 'MAX_CLIENTS-1'),
|
||||
NetIntAny("m_Type"),
|
||||
NetIntAny("m_SwitchNumber", -1),
|
||||
NetIntAny("m_Subtype", -1),
|
||||
]),
|
||||
|
||||
NetObjectEx("DDNetProjectile", "ddnet-projectile@netobj.ddnet.tw", [
|
||||
NetIntAny("m_X"),
|
||||
NetIntAny("m_Y"),
|
||||
NetIntAny("m_VelX"),
|
||||
NetIntAny("m_VelY"),
|
||||
NetIntRange("m_Type", 0, 'NUM_WEAPONS-1'),
|
||||
NetTick("m_StartTick"),
|
||||
NetIntRange("m_Owner", -1, 'MAX_CLIENTS-1'),
|
||||
NetIntAny("m_SwitchNumber"),
|
||||
NetIntAny("m_TuneZone"),
|
||||
NetIntAny("m_Flags"),
|
||||
]),
|
||||
|
||||
NetObjectEx("DDNetPickup", "pickup@netobj.ddnet.tw", [
|
||||
NetIntAny("m_X"),
|
||||
NetIntAny("m_Y"),
|
||||
NetIntRange("m_Type", 0, 'max_int'),
|
||||
NetIntRange("m_Subtype", 0, 'max_int'),
|
||||
NetIntAny("m_SwitchNumber"),
|
||||
]),
|
||||
|
||||
## Events
|
||||
|
|
|
@ -123,6 +123,7 @@ enum
|
|||
VERSION_DDNET_WEAPON_SHIELDS = 16010,
|
||||
VERSION_DDNET_NEW_HUD = 16020,
|
||||
VERSION_DDNET_MULTI_LASER = 16040,
|
||||
VERSION_DDNET_ENTITY_NETOBJS = 16200,
|
||||
};
|
||||
|
||||
typedef std::bitset<MAX_CLIENTS> CClientMask;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <game/client/gameclient.h>
|
||||
#include <game/client/laser_data.h>
|
||||
#include <game/client/pickup_data.h>
|
||||
#include <game/client/projectile_data.h>
|
||||
#include <game/client/render.h>
|
||||
|
||||
|
@ -257,6 +258,7 @@ void CItems::RenderLaser(const CLaserData *pCurrent, bool IsPredicted)
|
|||
ColorOut = g_Config.m_ClLaserShotgunOutlineColor;
|
||||
ColorIn = g_Config.m_ClLaserShotgunInnerColor;
|
||||
break;
|
||||
case LASERTYPE_DRAGGER:
|
||||
case LASERTYPE_DOOR:
|
||||
ColorOut = g_Config.m_ClLaserDoorOutlineColor;
|
||||
ColorIn = g_Config.m_ClLaserDoorInnerColor;
|
||||
|
@ -265,6 +267,19 @@ void CItems::RenderLaser(const CLaserData *pCurrent, bool IsPredicted)
|
|||
ColorOut = g_Config.m_ClLaserFreezeOutlineColor;
|
||||
ColorIn = g_Config.m_ClLaserFreezeInnerColor;
|
||||
break;
|
||||
case LASERTYPE_GUN:
|
||||
case LASERTYPE_PLASMA:
|
||||
if(pCurrent->m_Subtype == LASERGUNTYPE_FREEZE || pCurrent->m_Subtype == LASERGUNTYPE_EXPFREEZE)
|
||||
{
|
||||
ColorOut = g_Config.m_ClLaserFreezeOutlineColor;
|
||||
ColorIn = g_Config.m_ClLaserFreezeInnerColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
ColorOut = g_Config.m_ClLaserRifleOutlineColor;
|
||||
ColorIn = g_Config.m_ClLaserRifleInnerColor;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ColorOut = g_Config.m_ClLaserRifleOutlineColor;
|
||||
ColorIn = g_Config.m_ClLaserRifleInnerColor;
|
||||
|
@ -402,22 +417,14 @@ void CItems::OnRender()
|
|||
const void *pData = Ent.m_pData;
|
||||
const CNetObj_EntityEx *pEntEx = Ent.m_pDataEx;
|
||||
|
||||
bool Inactive = false;
|
||||
if(pEntEx)
|
||||
Inactive = !IsSuper && pEntEx->m_SwitchNumber > 0 && pEntEx->m_SwitchNumber < (int)aSwitchers.size() && !aSwitchers[pEntEx->m_SwitchNumber].m_aStatus[SwitcherTeam];
|
||||
|
||||
if(Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE)
|
||||
if(Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDRACEPROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE)
|
||||
{
|
||||
CProjectileData Data;
|
||||
if(Item.m_Type == NETOBJTYPE_PROJECTILE)
|
||||
{
|
||||
Data = ExtractProjectileInfo((const CNetObj_Projectile *)pData, &GameClient()->m_GameWorld);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = ExtractProjectileInfoDDNet((const CNetObj_DDNetProjectile *)pData, &GameClient()->m_GameWorld);
|
||||
}
|
||||
CProjectileData Data = ExtractProjectileInfo(Item.m_Type, pData, &GameClient()->m_GameWorld, pEntEx);
|
||||
bool Inactive = !IsSuper && Data.m_SwitchNumber > 0 && Data.m_SwitchNumber < (int)aSwitchers.size() && !aSwitchers[Data.m_SwitchNumber].m_aStatus[SwitcherTeam];
|
||||
if(Inactive && (Data.m_Explosive ? BlinkingProjEx : BlinkingProj))
|
||||
continue;
|
||||
if(UsePredicted)
|
||||
|
||||
{
|
||||
if(auto *pProj = (CProjectile *)GameClient()->m_GameWorld.FindMatch(Item.m_ID, Item.m_Type, pData))
|
||||
{
|
||||
|
@ -434,12 +441,13 @@ void CItems::OnRender()
|
|||
continue;
|
||||
}
|
||||
}
|
||||
if(Inactive && (Data.m_Explosive ? BlinkingProjEx : BlinkingProj))
|
||||
continue;
|
||||
RenderProjectile(&Data, Item.m_ID);
|
||||
}
|
||||
else if(Item.m_Type == NETOBJTYPE_PICKUP)
|
||||
else if(Item.m_Type == NETOBJTYPE_PICKUP || Item.m_Type == NETOBJTYPE_DDNETPICKUP)
|
||||
{
|
||||
CPickupData Data = ExtractPickupInfo(Item.m_Type, pData, pEntEx);
|
||||
bool Inactive = !IsSuper && Data.m_SwitchNumber > 0 && Data.m_SwitchNumber < (int)aSwitchers.size() && !aSwitchers[Data.m_SwitchNumber].m_aStatus[SwitcherTeam];
|
||||
|
||||
if(Inactive && BlinkingPickup)
|
||||
continue;
|
||||
if(UsePredicted)
|
||||
|
@ -461,46 +469,43 @@ void CItems::OnRender()
|
|||
continue;
|
||||
}
|
||||
|
||||
CLaserData Data;
|
||||
if(Item.m_Type == NETOBJTYPE_LASER)
|
||||
CLaserData Data = ExtractLaserInfo(Item.m_Type, pData, &GameClient()->m_GameWorld, pEntEx);
|
||||
bool Inactive = !IsSuper && Data.m_SwitchNumber > 0 && Data.m_SwitchNumber < (int)aSwitchers.size() && !aSwitchers[Data.m_SwitchNumber].m_aStatus[SwitcherTeam];
|
||||
|
||||
if(Data.m_Type == LASERTYPE_FREEZE)
|
||||
{
|
||||
Data = ExtractLaserInfo((const CNetObj_Laser *)pData, &GameClient()->m_GameWorld);
|
||||
if(Inactive && BlinkingLight)
|
||||
continue;
|
||||
Data.m_StartTick = DraggerStartTick;
|
||||
}
|
||||
else
|
||||
else if(Data.m_Type == LASERTYPE_GUN)
|
||||
{
|
||||
Data = ExtractLaserInfoDDNet((const CNetObj_DDNetLaser *)pData, &GameClient()->m_GameWorld);
|
||||
if(Inactive && BlinkingGun)
|
||||
continue;
|
||||
Data.m_StartTick = GunStartTick;
|
||||
}
|
||||
else if(Data.m_Type == LASERTYPE_DRAGGER)
|
||||
{
|
||||
if(Inactive && BlinkingDragger)
|
||||
continue;
|
||||
Data.m_StartTick = DraggerStartTick;
|
||||
}
|
||||
else if(Data.m_Type == LASERTYPE_DOOR)
|
||||
{
|
||||
if(Inactive || IsSuper)
|
||||
{
|
||||
Data.m_From.x = Data.m_To.x;
|
||||
Data.m_From.y = Data.m_To.y;
|
||||
}
|
||||
Data.m_StartTick = Client()->GameTick(g_Config.m_ClDummy);
|
||||
}
|
||||
else if(Data.m_Type >= NUM_LASERTYPES)
|
||||
{
|
||||
if(Inactive && BlinkingDragger)
|
||||
continue;
|
||||
Data.m_StartTick = Client()->GameTick(g_Config.m_ClDummy);
|
||||
}
|
||||
|
||||
if(pEntEx)
|
||||
{
|
||||
if(pEntEx->m_EntityClass == ENTITYCLASS_LIGHT)
|
||||
{
|
||||
if(Inactive && BlinkingLight)
|
||||
continue;
|
||||
Data.m_StartTick = DraggerStartTick;
|
||||
}
|
||||
if(pEntEx->m_EntityClass >= ENTITYCLASS_GUN_NORMAL && pEntEx->m_EntityClass <= ENTITYCLASS_GUN_UNFREEZE)
|
||||
{
|
||||
if(Inactive && BlinkingGun)
|
||||
continue;
|
||||
Data.m_StartTick = GunStartTick;
|
||||
}
|
||||
if(pEntEx->m_EntityClass >= ENTITYCLASS_DRAGGER_WEAK && pEntEx->m_EntityClass <= ENTITYCLASS_DRAGGER_STRONG)
|
||||
{
|
||||
if(Inactive && BlinkingDragger)
|
||||
continue;
|
||||
Data.m_StartTick = DraggerStartTick;
|
||||
}
|
||||
if(pEntEx->m_EntityClass == ENTITYCLASS_DOOR)
|
||||
{
|
||||
if(Inactive || IsSuper)
|
||||
{
|
||||
Data.m_From.x = Data.m_To.x;
|
||||
Data.m_From.y = Data.m_To.y;
|
||||
}
|
||||
Data.m_StartTick = Client()->GameTick(g_Config.m_ClDummy);
|
||||
}
|
||||
}
|
||||
RenderLaser(&Data);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3316,7 +3316,7 @@ void CGameClient::SnapCollectEntities()
|
|||
const void *pData = Client()->SnapGetItem(IClient::SNAP_CURRENT, Index, &Item);
|
||||
if(Item.m_Type == NETOBJTYPE_ENTITYEX)
|
||||
vItemEx.push_back({Item, pData, 0});
|
||||
else if(Item.m_Type == NETOBJTYPE_PICKUP || Item.m_Type == NETOBJTYPE_LASER || Item.m_Type == NETOBJTYPE_DDNETLASER || Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE)
|
||||
else if(Item.m_Type == NETOBJTYPE_PICKUP || Item.m_Type == NETOBJTYPE_DDNETPICKUP || Item.m_Type == NETOBJTYPE_LASER || Item.m_Type == NETOBJTYPE_DDNETLASER || Item.m_Type == NETOBJTYPE_PROJECTILE || Item.m_Type == NETOBJTYPE_DDRACEPROJECTILE || Item.m_Type == NETOBJTYPE_DDNETPROJECTILE)
|
||||
vItemData.push_back({Item, pData, 0});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,18 +9,52 @@
|
|||
|
||||
#include <game/collision.h>
|
||||
|
||||
CLaserData ExtractLaserInfo(const CNetObj_Laser *pLaser, CGameWorld *pGameWorld)
|
||||
CLaserData ExtractLaserInfo(int NetObjType, const void *pData, CGameWorld *pGameWorld, const CNetObj_EntityEx *pEntEx)
|
||||
{
|
||||
CLaserData Result = {vec2(0, 0)};
|
||||
Result.m_From.x = pLaser->m_FromX;
|
||||
Result.m_From.y = pLaser->m_FromY;
|
||||
Result.m_To.x = pLaser->m_X;
|
||||
Result.m_To.y = pLaser->m_Y;
|
||||
Result.m_StartTick = pLaser->m_StartTick;
|
||||
Result.m_ExtraInfo = false;
|
||||
Result.m_Owner = -1;
|
||||
Result.m_Type = -1;
|
||||
Result.m_TuneZone = pGameWorld && pGameWorld->m_WorldConfig.m_UseTuneZones ? pGameWorld->Collision()->IsTune(pGameWorld->Collision()->GetMapIndex(Result.m_From)) : 0;
|
||||
|
||||
if(NetObjType == NETOBJTYPE_DDNETLASER)
|
||||
{
|
||||
Result = ExtractLaserInfoDDNet((const CNetObj_DDNetLaser *)pData, pGameWorld);
|
||||
}
|
||||
else
|
||||
{
|
||||
CNetObj_Laser *pLaser = (CNetObj_Laser *)pData;
|
||||
|
||||
Result.m_From.x = pLaser->m_FromX;
|
||||
Result.m_From.y = pLaser->m_FromY;
|
||||
Result.m_To.x = pLaser->m_X;
|
||||
Result.m_To.y = pLaser->m_Y;
|
||||
Result.m_StartTick = pLaser->m_StartTick;
|
||||
Result.m_ExtraInfo = false;
|
||||
Result.m_Owner = -1;
|
||||
Result.m_Type = -1;
|
||||
Result.m_SwitchNumber = 0;
|
||||
Result.m_Subtype = -1;
|
||||
Result.m_TuneZone = pGameWorld && pGameWorld->m_WorldConfig.m_UseTuneZones ? pGameWorld->Collision()->IsTune(pGameWorld->Collision()->GetMapIndex(Result.m_From)) : 0;
|
||||
}
|
||||
|
||||
if(pEntEx && !(NetObjType == NETOBJTYPE_DDNETLASER && Result.m_SwitchNumber >= 0))
|
||||
{
|
||||
Result.m_SwitchNumber = pEntEx->m_SwitchNumber;
|
||||
if(pEntEx->m_EntityClass == ENTITYCLASS_LIGHT)
|
||||
{
|
||||
Result.m_Type = LASERTYPE_FREEZE;
|
||||
}
|
||||
else if(pEntEx->m_EntityClass >= ENTITYCLASS_GUN_NORMAL && pEntEx->m_EntityClass <= ENTITYCLASS_GUN_UNFREEZE)
|
||||
{
|
||||
Result.m_Type = LASERTYPE_GUN;
|
||||
}
|
||||
else if(pEntEx->m_EntityClass >= ENTITYCLASS_DRAGGER_WEAK && pEntEx->m_EntityClass <= ENTITYCLASS_DRAGGER_STRONG)
|
||||
{
|
||||
Result.m_Type = LASERTYPE_DRAGGER;
|
||||
}
|
||||
else if(pEntEx->m_EntityClass == ENTITYCLASS_DOOR)
|
||||
{
|
||||
Result.m_Type = LASERTYPE_DOOR;
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -35,6 +69,8 @@ CLaserData ExtractLaserInfoDDNet(const CNetObj_DDNetLaser *pLaser, CGameWorld *p
|
|||
Result.m_ExtraInfo = true;
|
||||
Result.m_Owner = pLaser->m_Owner;
|
||||
Result.m_Type = pLaser->m_Type;
|
||||
Result.m_SwitchNumber = pLaser->m_SwitchNumber;
|
||||
Result.m_Subtype = pLaser->m_Subtype;
|
||||
Result.m_TuneZone = pGameWorld && pGameWorld->m_WorldConfig.m_UseTuneZones ? pGameWorld->Collision()->IsTune(pGameWorld->Collision()->GetMapIndex(Result.m_From)) : 0;
|
||||
return Result;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
struct CNetObj_Laser;
|
||||
struct CNetObj_DDNetLaser;
|
||||
struct CNetObj_EntityEx;
|
||||
|
||||
class CLaserData
|
||||
{
|
||||
|
@ -18,11 +19,13 @@ public:
|
|||
// The rest is only set if m_ExtraInfo is true.
|
||||
int m_Owner;
|
||||
int m_Type;
|
||||
int m_SwitchNumber;
|
||||
int m_Subtype;
|
||||
// TuneZone is introduced locally
|
||||
int m_TuneZone;
|
||||
};
|
||||
|
||||
CLaserData ExtractLaserInfo(const CNetObj_Laser *pLaser, class CGameWorld *pGameWorld);
|
||||
CLaserData ExtractLaserInfo(int NetObjType, const void *pData, class CGameWorld *pGameWorld, const CNetObj_EntityEx *pEntEx);
|
||||
CLaserData ExtractLaserInfoDDNet(const CNetObj_DDNetLaser *pLaser, class CGameWorld *pGameWorld);
|
||||
|
||||
#endif // GAME_CLIENT_LASER_DATA_H
|
||||
|
|
41
src/game/client/pickup_data.cpp
Normal file
41
src/game/client/pickup_data.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* (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. */
|
||||
|
||||
#include "pickup_data.h"
|
||||
|
||||
#include <engine/shared/snapshot.h>
|
||||
#include <game/collision.h>
|
||||
#include <game/generated/protocol.h>
|
||||
|
||||
CPickupData ExtractPickupInfo(int NetObjType, const void *pData, const CNetObj_EntityEx *pEntEx)
|
||||
{
|
||||
if(NetObjType == NETOBJTYPE_DDNETPICKUP)
|
||||
{
|
||||
return ExtractPickupInfoDDNet((CNetObj_DDNetPickup *)pData);
|
||||
}
|
||||
|
||||
CNetObj_Pickup *pPickup = (CNetObj_Pickup *)pData;
|
||||
|
||||
CPickupData Result = {vec2(0, 0)};
|
||||
|
||||
Result.m_Pos.x = pPickup->m_X;
|
||||
Result.m_Pos.y = pPickup->m_Y;
|
||||
Result.m_Type = pPickup->m_Type;
|
||||
Result.m_Subtype = pPickup->m_Subtype;
|
||||
Result.m_SwitchNumber = pEntEx ? pEntEx->m_SwitchNumber : 0;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
CPickupData ExtractPickupInfoDDNet(const CNetObj_DDNetPickup *pPickup)
|
||||
{
|
||||
CPickupData Result = {vec2(0, 0)};
|
||||
|
||||
Result.m_Pos.x = pPickup->m_X;
|
||||
Result.m_Pos.y = pPickup->m_Y;
|
||||
Result.m_Type = pPickup->m_Type;
|
||||
Result.m_Subtype = pPickup->m_Subtype;
|
||||
Result.m_SwitchNumber = pPickup->m_SwitchNumber;
|
||||
|
||||
return Result;
|
||||
}
|
24
src/game/client/pickup_data.h
Normal file
24
src/game/client/pickup_data.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* (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. */
|
||||
#ifndef GAME_CLIENT_PICKUP_DATA_H
|
||||
#define GAME_CLIENT_PICKUP_DATA_H
|
||||
|
||||
#include <base/vmath.h>
|
||||
|
||||
struct CNetObj_Pickup;
|
||||
struct CNetObj_DDNetPickup;
|
||||
struct CNetObj_EntityEx;
|
||||
|
||||
class CPickupData
|
||||
{
|
||||
public:
|
||||
vec2 m_Pos;
|
||||
int m_Type;
|
||||
int m_Subtype;
|
||||
int m_SwitchNumber;
|
||||
};
|
||||
|
||||
CPickupData ExtractPickupInfo(int NetObjType, const void *pData, const CNetObj_EntityEx *pEntEx);
|
||||
CPickupData ExtractPickupInfoDDNet(const CNetObj_DDNetPickup *pPickup);
|
||||
|
||||
#endif // GAME_CLIENT_PICKUP_DATA_H
|
|
@ -208,15 +208,6 @@ CLaser::CLaser(CGameWorld *pGameWorld, int ID, CLaserData *pLaser) :
|
|||
m_ID = ID;
|
||||
}
|
||||
|
||||
void CLaser::FillInfo(CNetObj_Laser *pLaser)
|
||||
{
|
||||
pLaser->m_X = (int)m_Pos.x;
|
||||
pLaser->m_Y = (int)m_Pos.y;
|
||||
pLaser->m_FromX = (int)m_From.x;
|
||||
pLaser->m_FromY = (int)m_From.y;
|
||||
pLaser->m_StartTick = m_EvalTick;
|
||||
}
|
||||
|
||||
bool CLaser::Match(CLaser *pLaser)
|
||||
{
|
||||
if(pLaser->m_EvalTick != m_EvalTick)
|
||||
|
@ -240,6 +231,8 @@ CLaserData CLaser::GetData() const
|
|||
Result.m_ExtraInfo = true;
|
||||
Result.m_Owner = m_Owner;
|
||||
Result.m_Type = m_Type == WEAPON_SHOTGUN ? LASERTYPE_SHOTGUN : LASERTYPE_RIFLE;
|
||||
Result.m_Subtype = -1;
|
||||
Result.m_TuneZone = m_TuneZone;
|
||||
Result.m_SwitchNumber = m_Number;
|
||||
return Result;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ public:
|
|||
const int &GetOwner() { return m_Owner; }
|
||||
const int &GetEvalTick() { return m_EvalTick; }
|
||||
CLaser(CGameWorld *pGameWorld, int ID, CLaserData *pLaser);
|
||||
void FillInfo(CNetObj_Laser *pLaser);
|
||||
bool Match(CLaser *pLaser);
|
||||
CLaserData GetData() const;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
/* If you are missing that file, acquire a complete release at teeworlds.com. */
|
||||
#include "pickup.h"
|
||||
#include "character.h"
|
||||
#include <game/client/pickup_data.h>
|
||||
#include <game/collision.h>
|
||||
#include <game/generated/protocol.h>
|
||||
#include <game/mapitems.h>
|
||||
|
@ -141,24 +142,17 @@ void CPickup::Move()
|
|||
}
|
||||
}
|
||||
|
||||
CPickup::CPickup(CGameWorld *pGameWorld, int ID, CNetObj_Pickup *pPickup, const CNetObj_EntityEx *pEntEx) :
|
||||
CPickup::CPickup(CGameWorld *pGameWorld, int ID, const CPickupData *pPickup) :
|
||||
CEntity(pGameWorld, CGameWorld::ENTTYPE_PICKUP)
|
||||
{
|
||||
m_Pos.x = pPickup->m_X;
|
||||
m_Pos.y = pPickup->m_Y;
|
||||
m_Pos = pPickup->m_Pos;
|
||||
m_Type = pPickup->m_Type;
|
||||
m_Subtype = pPickup->m_Subtype;
|
||||
m_Core = vec2(0.f, 0.f);
|
||||
m_IsCoreActive = false;
|
||||
m_ID = ID;
|
||||
m_Layer = LAYER_GAME;
|
||||
m_Number = 0;
|
||||
|
||||
if(pEntEx)
|
||||
{
|
||||
m_Layer = pEntEx->m_Layer;
|
||||
m_Number = pEntEx->m_SwitchNumber;
|
||||
}
|
||||
m_Number = pPickup->m_SwitchNumber;
|
||||
m_Layer = m_Number > 0 ? LAYER_SWITCH : LAYER_GAME;
|
||||
}
|
||||
|
||||
void CPickup::FillInfo(CNetObj_Pickup *pPickup)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#include <game/client/prediction/entity.h>
|
||||
|
||||
class CPickupData;
|
||||
|
||||
class CPickup : public CEntity
|
||||
{
|
||||
public:
|
||||
|
@ -12,7 +14,7 @@ public:
|
|||
|
||||
void Tick() override;
|
||||
|
||||
CPickup(CGameWorld *pGameWorld, int ID, CNetObj_Pickup *pPickup, const CNetObj_EntityEx *pEntEx = 0);
|
||||
CPickup(CGameWorld *pGameWorld, int ID, const CPickupData *pPickup);
|
||||
void FillInfo(CNetObj_Pickup *pPickup);
|
||||
bool Match(CPickup *pPickup);
|
||||
bool InDDNetTile() { return m_IsCoreActive; }
|
||||
|
|
|
@ -155,7 +155,7 @@ void CProjectile::SetBouncing(int Value)
|
|||
m_Bouncing = Value;
|
||||
}
|
||||
|
||||
CProjectile::CProjectile(CGameWorld *pGameWorld, int ID, CProjectileData *pProj, const CNetObj_EntityEx *pEntEx) :
|
||||
CProjectile::CProjectile(CGameWorld *pGameWorld, int ID, const CProjectileData *pProj) :
|
||||
CEntity(pGameWorld, CGameWorld::ENTTYPE_PROJECTILE)
|
||||
{
|
||||
m_Pos = pProj->m_StartPos;
|
||||
|
@ -191,14 +191,8 @@ CProjectile::CProjectile(CGameWorld *pGameWorld, int ID, CProjectileData *pProj,
|
|||
Lifetime = GetTuning(m_TuneZone)->m_ShotgunLifetime * GameWorld()->GameTickSpeed();
|
||||
m_LifeSpan = Lifetime - (pGameWorld->GameTick() - m_StartTick);
|
||||
m_ID = ID;
|
||||
m_Layer = LAYER_GAME;
|
||||
m_Number = 0;
|
||||
|
||||
if(pEntEx)
|
||||
{
|
||||
m_Layer = LAYER_SWITCH;
|
||||
m_Number = pEntEx->m_SwitchNumber;
|
||||
}
|
||||
m_Number = pProj->m_SwitchNumber;
|
||||
m_Layer = m_Number > 0 ? LAYER_SWITCH : LAYER_GAME;
|
||||
}
|
||||
|
||||
CProjectileData CProjectile::GetData() const
|
||||
|
@ -214,6 +208,7 @@ CProjectileData CProjectile::GetData() const
|
|||
Result.m_Bouncing = m_Bouncing;
|
||||
Result.m_Freeze = m_Freeze;
|
||||
Result.m_TuneZone = m_TuneZone;
|
||||
Result.m_SwitchNumber = m_Number;
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
const vec2 &GetDirection() { return m_Direction; }
|
||||
const int &GetOwner() { return m_Owner; }
|
||||
const int &GetStartTick() { return m_StartTick; }
|
||||
CProjectile(CGameWorld *pGameWorld, int ID, CProjectileData *pProj, const CNetObj_EntityEx *pEntEx = 0);
|
||||
CProjectile(CGameWorld *pGameWorld, int ID, const CProjectileData *pProj);
|
||||
|
||||
private:
|
||||
vec2 m_Direction;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <algorithm>
|
||||
#include <engine/shared/config.h>
|
||||
#include <game/client/laser_data.h>
|
||||
#include <game/client/pickup_data.h>
|
||||
#include <game/client/projectile_data.h>
|
||||
#include <game/mapitems.h>
|
||||
#include <utility>
|
||||
|
@ -408,18 +409,10 @@ void CGameWorld::NetCharAdd(int ObjID, CNetObj_Character *pCharObj, CNetObj_DDNe
|
|||
|
||||
void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const CNetObj_EntityEx *pDataEx)
|
||||
{
|
||||
if((ObjType == NETOBJTYPE_PROJECTILE || ObjType == NETOBJTYPE_DDNETPROJECTILE) && m_WorldConfig.m_PredictWeapons)
|
||||
if((ObjType == NETOBJTYPE_PROJECTILE || ObjType == NETOBJTYPE_DDRACEPROJECTILE || ObjType == NETOBJTYPE_DDNETPROJECTILE) && m_WorldConfig.m_PredictWeapons)
|
||||
{
|
||||
CProjectileData Data;
|
||||
if(ObjType == NETOBJTYPE_PROJECTILE)
|
||||
{
|
||||
Data = ExtractProjectileInfo((const CNetObj_Projectile *)pObjData, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = ExtractProjectileInfoDDNet((const CNetObj_DDNetProjectile *)pObjData, this);
|
||||
}
|
||||
CProjectile NetProj = CProjectile(this, ObjID, &Data, pDataEx);
|
||||
CProjectileData Data = ExtractProjectileInfo(ObjType, pObjData, this, pDataEx);
|
||||
CProjectile NetProj = CProjectile(this, ObjID, &Data);
|
||||
|
||||
if(NetProj.m_Type != WEAPON_SHOTGUN && absolute(length(NetProj.m_Direction) - 1.f) > 0.02f) // workaround to skip grenades on ball mod
|
||||
return;
|
||||
|
@ -471,9 +464,10 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C
|
|||
CProjectile *pProj = new CProjectile(NetProj);
|
||||
InsertEntity(pProj);
|
||||
}
|
||||
else if(ObjType == NETOBJTYPE_PICKUP && m_WorldConfig.m_PredictWeapons)
|
||||
else if((ObjType == NETOBJTYPE_PICKUP || ObjType == NETOBJTYPE_DDNETPICKUP) && m_WorldConfig.m_PredictWeapons)
|
||||
{
|
||||
CPickup NetPickup = CPickup(this, ObjID, (CNetObj_Pickup *)pObjData, pDataEx);
|
||||
CPickupData Data = ExtractPickupInfo(ObjType, pObjData, pDataEx);
|
||||
CPickup NetPickup = CPickup(this, ObjID, &Data);
|
||||
if(CPickup *pPickup = (CPickup *)GetEntity(ObjID, ENTTYPE_PICKUP))
|
||||
{
|
||||
if(NetPickup.Match(pPickup))
|
||||
|
@ -488,15 +482,12 @@ void CGameWorld::NetObjAdd(int ObjID, int ObjType, const void *pObjData, const C
|
|||
}
|
||||
else if((ObjType == NETOBJTYPE_LASER || ObjType == NETOBJTYPE_DDNETLASER) && m_WorldConfig.m_PredictWeapons)
|
||||
{
|
||||
CLaserData Data;
|
||||
if(ObjType == NETOBJTYPE_LASER)
|
||||
CLaserData Data = ExtractLaserInfo(ObjType, pObjData, this, pDataEx);
|
||||
if(Data.m_Type >= 0 && Data.m_Type != LASERTYPE_RIFLE && Data.m_Type != LASERTYPE_SHOTGUN)
|
||||
{
|
||||
Data = ExtractLaserInfo((const CNetObj_Laser *)pObjData, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = ExtractLaserInfoDDNet((const CNetObj_DDNetLaser *)pObjData, this);
|
||||
return;
|
||||
}
|
||||
|
||||
CLaser NetLaser = CLaser(this, ObjID, &Data);
|
||||
CLaser *pMatching = 0;
|
||||
if(CLaser *pLaser = dynamic_cast<CLaser *>(GetEntity(ObjID, ENTTYPE_LASER)))
|
||||
|
@ -618,28 +609,22 @@ void CGameWorld::CopyWorld(CGameWorld *pFrom)
|
|||
|
||||
CEntity *CGameWorld::FindMatch(int ObjID, int ObjType, const void *pObjData)
|
||||
{
|
||||
#define FindType(EntType, EntClass, ObjClass) \
|
||||
{ \
|
||||
CEntity *pEnt = GetEntity(ObjID, EntType); \
|
||||
if(pEnt && EntClass(this, ObjID, (ObjClass *)pObjData).Match((EntClass *)pEnt)) \
|
||||
return pEnt; \
|
||||
return 0; \
|
||||
}
|
||||
switch(ObjType)
|
||||
{
|
||||
case NETOBJTYPE_CHARACTER: FindType(ENTTYPE_CHARACTER, CCharacter, CNetObj_Character);
|
||||
case NETOBJTYPE_CHARACTER:
|
||||
{
|
||||
CCharacter *pEnt = (CCharacter *)GetEntity(ObjID, ENTTYPE_CHARACTER);
|
||||
if(pEnt && CCharacter(this, ObjID, (CNetObj_Character *)pObjData).Match((CCharacter *)pEnt))
|
||||
{
|
||||
return pEnt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case NETOBJTYPE_PROJECTILE:
|
||||
case NETOBJTYPE_DDRACEPROJECTILE:
|
||||
case NETOBJTYPE_DDNETPROJECTILE:
|
||||
{
|
||||
CProjectileData Data;
|
||||
if(ObjType == NETOBJTYPE_PROJECTILE)
|
||||
{
|
||||
Data = ExtractProjectileInfo((const CNetObj_Projectile *)pObjData, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = ExtractProjectileInfoDDNet((const CNetObj_DDNetProjectile *)pObjData, this);
|
||||
}
|
||||
CProjectileData Data = ExtractProjectileInfo(ObjType, pObjData, this, nullptr);
|
||||
CProjectile *pEnt = (CProjectile *)GetEntity(ObjID, ENTTYPE_PROJECTILE);
|
||||
if(pEnt && CProjectile(this, ObjID, &Data).Match(pEnt))
|
||||
{
|
||||
|
@ -650,15 +635,7 @@ CEntity *CGameWorld::FindMatch(int ObjID, int ObjType, const void *pObjData)
|
|||
case NETOBJTYPE_LASER:
|
||||
case NETOBJTYPE_DDNETLASER:
|
||||
{
|
||||
CLaserData Data;
|
||||
if(ObjType == NETOBJTYPE_LASER)
|
||||
{
|
||||
Data = ExtractLaserInfo((const CNetObj_Laser *)pObjData, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = ExtractLaserInfoDDNet((const CNetObj_DDNetLaser *)pObjData, this);
|
||||
}
|
||||
CLaserData Data = ExtractLaserInfo(ObjType, pObjData, this, nullptr);
|
||||
CLaser *pEnt = (CLaser *)GetEntity(ObjID, ENTTYPE_LASER);
|
||||
if(pEnt && CLaser(this, ObjID, &Data).Match(pEnt))
|
||||
{
|
||||
|
@ -666,7 +643,17 @@ CEntity *CGameWorld::FindMatch(int ObjID, int ObjType, const void *pObjData)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
case NETOBJTYPE_PICKUP: FindType(ENTTYPE_PICKUP, CPickup, CNetObj_Pickup);
|
||||
case NETOBJTYPE_PICKUP:
|
||||
case NETOBJTYPE_DDNETPICKUP:
|
||||
{
|
||||
CPickupData Data = ExtractPickupInfo(ObjType, pObjData, nullptr);
|
||||
CPickup *pEnt = (CPickup *)GetEntity(ObjID, ENTTYPE_PICKUP);
|
||||
if(pEnt && CPickup(this, ObjID, &Data).Match(pEnt))
|
||||
{
|
||||
return pEnt;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -11,16 +11,20 @@
|
|||
|
||||
bool UseProjectileExtraInfo(const CNetObj_Projectile *pProj)
|
||||
{
|
||||
return pProj->m_VelY >= 0 && (pProj->m_VelY & PROJECTILEFLAG_IS_DDNET) != 0;
|
||||
return pProj->m_VelY >= 0 && (pProj->m_VelY & LEGACYPROJECTILEFLAG_IS_DDNET) != 0;
|
||||
}
|
||||
|
||||
CProjectileData ExtractProjectileInfo(const CNetObj_Projectile *pProj, CGameWorld *pGameWorld)
|
||||
CProjectileData ExtractProjectileInfo(int NetObjType, const void *pData, CGameWorld *pGameWorld, const CNetObj_EntityEx *pEntEx)
|
||||
{
|
||||
if(UseProjectileExtraInfo(pProj))
|
||||
CNetObj_Projectile *pProj = (CNetObj_Projectile *)pData;
|
||||
|
||||
if(NetObjType == NETOBJTYPE_DDNETPROJECTILE)
|
||||
{
|
||||
CNetObj_DDNetProjectile Proj;
|
||||
mem_copy(&Proj, pProj, sizeof(Proj));
|
||||
return ExtractProjectileInfoDDNet(&Proj, pGameWorld);
|
||||
return ExtractProjectileInfoDDNet((CNetObj_DDNetProjectile *)pData);
|
||||
}
|
||||
else if(NetObjType == NETOBJTYPE_DDRACEPROJECTILE || (NetObjType == NETOBJTYPE_PROJECTILE && UseProjectileExtraInfo(pProj)))
|
||||
{
|
||||
return ExtractProjectileInfoDDRace((CNetObj_DDRaceProjectile *)pData, pGameWorld, pEntEx);
|
||||
}
|
||||
|
||||
CProjectileData Result = {vec2(0, 0)};
|
||||
|
@ -33,10 +37,11 @@ CProjectileData ExtractProjectileInfo(const CNetObj_Projectile *pProj, CGameWorl
|
|||
Result.m_ExtraInfo = false;
|
||||
Result.m_Owner = -1;
|
||||
Result.m_TuneZone = pGameWorld && pGameWorld->m_WorldConfig.m_UseTuneZones ? pGameWorld->Collision()->IsTune(pGameWorld->Collision()->GetMapIndex(Result.m_StartPos)) : 0;
|
||||
Result.m_SwitchNumber = pEntEx ? pEntEx->m_SwitchNumber : 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
CProjectileData ExtractProjectileInfoDDNet(const CNetObj_DDNetProjectile *pProj, CGameWorld *pGameWorld)
|
||||
CProjectileData ExtractProjectileInfoDDRace(const CNetObj_DDRaceProjectile *pProj, CGameWorld *pGameWorld, const CNetObj_EntityEx *pEntEx)
|
||||
{
|
||||
CProjectileData Result = {vec2(0, 0)};
|
||||
|
||||
|
@ -50,15 +55,52 @@ CProjectileData ExtractProjectileInfoDDNet(const CNetObj_DDNetProjectile *pProj,
|
|||
|
||||
Result.m_ExtraInfo = true;
|
||||
Result.m_Owner = pProj->m_Data & 255;
|
||||
if(pProj->m_Data & PROJECTILEFLAG_NO_OWNER || Result.m_Owner < 0 || Result.m_Owner >= MAX_CLIENTS)
|
||||
if(pProj->m_Data & LEGACYPROJECTILEFLAG_NO_OWNER || Result.m_Owner < 0 || Result.m_Owner >= MAX_CLIENTS)
|
||||
{
|
||||
Result.m_Owner = -1;
|
||||
}
|
||||
// PROJECTILEFLAG_BOUNCE_HORIZONTAL, PROJECTILEFLAG_BOUNCE_VERTICAL
|
||||
// LEGACYPROJECTILEFLAG_BOUNCE_HORIZONTAL, LEGACYPROJECTILEFLAG_BOUNCE_VERTICAL
|
||||
Result.m_Bouncing = (pProj->m_Data >> 10) & 3;
|
||||
Result.m_Explosive = pProj->m_Data & PROJECTILEFLAG_EXPLOSIVE;
|
||||
Result.m_Freeze = pProj->m_Data & PROJECTILEFLAG_FREEZE;
|
||||
Result.m_Explosive = pProj->m_Data & LEGACYPROJECTILEFLAG_EXPLOSIVE;
|
||||
Result.m_Freeze = pProj->m_Data & LEGACYPROJECTILEFLAG_FREEZE;
|
||||
Result.m_TuneZone = pGameWorld && pGameWorld->m_WorldConfig.m_UseTuneZones ? pGameWorld->Collision()->IsTune(pGameWorld->Collision()->GetMapIndex(Result.m_StartPos)) : 0;
|
||||
Result.m_SwitchNumber = pEntEx ? pEntEx->m_SwitchNumber : 0;
|
||||
return Result;
|
||||
}
|
||||
|
||||
CProjectileData ExtractProjectileInfoDDNet(const CNetObj_DDNetProjectile *pProj)
|
||||
{
|
||||
CProjectileData Result = {vec2(0, 0)};
|
||||
|
||||
Result.m_StartPos = vec2(pProj->m_X / 100.0f, pProj->m_Y / 100.0f);
|
||||
Result.m_StartVel = vec2(pProj->m_VelX / 1e6f, pProj->m_VelY / 1e6f);
|
||||
|
||||
if(pProj->m_Flags & PROJECTILEFLAG_NORMALIZE_VEL)
|
||||
{
|
||||
Result.m_StartVel = normalize(Result.m_StartVel);
|
||||
}
|
||||
|
||||
Result.m_Type = pProj->m_Type;
|
||||
Result.m_StartTick = pProj->m_StartTick;
|
||||
|
||||
Result.m_ExtraInfo = true;
|
||||
Result.m_Owner = pProj->m_Owner;
|
||||
Result.m_SwitchNumber = pProj->m_SwitchNumber;
|
||||
Result.m_TuneZone = pProj->m_TuneZone;
|
||||
|
||||
Result.m_Bouncing = 0;
|
||||
if(pProj->m_Flags & PROJECTILEFLAG_BOUNCE_HORIZONTAL)
|
||||
{
|
||||
Result.m_Bouncing |= 1;
|
||||
}
|
||||
if(pProj->m_Flags & PROJECTILEFLAG_BOUNCE_VERTICAL)
|
||||
{
|
||||
Result.m_Bouncing |= 2;
|
||||
}
|
||||
|
||||
Result.m_Explosive = pProj->m_Flags & PROJECTILEFLAG_EXPLOSIVE;
|
||||
Result.m_Freeze = pProj->m_Flags & PROJECTILEFLAG_FREEZE;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -73,7 +115,7 @@ void SnapshotRemoveExtraProjectileInfo(unsigned char *pData)
|
|||
CNetObj_Projectile *pProj = (CNetObj_Projectile *)((void *)pItem->Data());
|
||||
if(UseProjectileExtraInfo(pProj))
|
||||
{
|
||||
CProjectileData Data = ExtractProjectileInfo(pProj, nullptr);
|
||||
CProjectileData Data = ExtractProjectileInfo(NETOBJTYPE_PROJECTILE, pProj, nullptr, nullptr);
|
||||
pProj->m_X = Data.m_StartPos.x;
|
||||
pProj->m_Y = Data.m_StartPos.y;
|
||||
pProj->m_VelX = (int)(Data.m_StartVel.x * 100.0f);
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
#include <base/vmath.h>
|
||||
|
||||
struct CNetObj_Projectile;
|
||||
struct CNetObj_DDRaceProjectile;
|
||||
struct CNetObj_DDNetProjectile;
|
||||
struct CNetObj_EntityEx;
|
||||
|
||||
class CProjectileData
|
||||
{
|
||||
|
@ -21,11 +23,13 @@ public:
|
|||
bool m_Explosive;
|
||||
int m_Bouncing;
|
||||
bool m_Freeze;
|
||||
int m_SwitchNumber;
|
||||
// TuneZone is introduced locally
|
||||
int m_TuneZone;
|
||||
};
|
||||
|
||||
CProjectileData ExtractProjectileInfo(const CNetObj_Projectile *pProj, class CGameWorld *pGameWorld);
|
||||
CProjectileData ExtractProjectileInfoDDNet(const CNetObj_DDNetProjectile *pProj, class CGameWorld *pGameWorld);
|
||||
CProjectileData ExtractProjectileInfo(int NetObjType, const void *pData, class CGameWorld *pGameWorld, const CNetObj_EntityEx *pEntEx);
|
||||
CProjectileData ExtractProjectileInfoDDRace(const CNetObj_DDRaceProjectile *pProj, class CGameWorld *pGameWorld, const CNetObj_EntityEx *pEntEx);
|
||||
CProjectileData ExtractProjectileInfoDDNet(const CNetObj_DDNetProjectile *pProj);
|
||||
|
||||
#endif // GAME_CLIENT_PROJECTILE_DATA_H
|
||||
|
|
|
@ -378,7 +378,8 @@ void CCharacter::FireWeapon()
|
|||
}
|
||||
|
||||
DoWeaponSwitch();
|
||||
vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
|
||||
vec2 MouseTarget = vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY);
|
||||
vec2 Direction = normalize(MouseTarget);
|
||||
|
||||
bool FullAuto = false;
|
||||
if(m_Core.m_ActiveWeapon == WEAPON_GRENADE || m_Core.m_ActiveWeapon == WEAPON_SHOTGUN || m_Core.m_ActiveWeapon == WEAPON_LASER)
|
||||
|
@ -513,7 +514,8 @@ void CCharacter::FireWeapon()
|
|||
Lifetime, //Span
|
||||
false, //Freeze
|
||||
false, //Explosive
|
||||
-1 //SoundImpact
|
||||
-1, //SoundImpact
|
||||
MouseTarget //InitDir
|
||||
);
|
||||
|
||||
GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE, TeamMask());
|
||||
|
@ -551,8 +553,9 @@ void CCharacter::FireWeapon()
|
|||
Lifetime, //Span
|
||||
false, //Freeze
|
||||
true, //Explosive
|
||||
SOUND_GRENADE_EXPLODE //SoundImpact
|
||||
); //SoundImpact
|
||||
SOUND_GRENADE_EXPLODE, //SoundImpact
|
||||
MouseTarget // MouseTarget
|
||||
);
|
||||
|
||||
GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE, TeamMask());
|
||||
}
|
||||
|
|
|
@ -52,19 +52,11 @@ void CDoor::Snap(int SnappingClient)
|
|||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
|
||||
CNetObj_EntityEx *pEntData = 0;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_SWITCH)
|
||||
pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
|
||||
|
||||
vec2 From;
|
||||
int StartTick;
|
||||
|
||||
if(pEntData)
|
||||
if(SnappingClientVersion >= VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
pEntData->m_SwitchNumber = m_Number;
|
||||
pEntData->m_Layer = m_Layer;
|
||||
pEntData->m_EntityClass = ENTITYCLASS_DOOR;
|
||||
|
||||
From = m_To;
|
||||
StartTick = 0;
|
||||
}
|
||||
|
@ -87,5 +79,5 @@ void CDoor::Snap(int SnappingClient)
|
|||
}
|
||||
|
||||
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
|
||||
m_Pos, From, StartTick, -1, LASERTYPE_DOOR);
|
||||
m_Pos, From, StartTick, -1, LASERTYPE_DOOR, 0, m_Number);
|
||||
}
|
||||
|
|
|
@ -186,17 +186,12 @@ void CDragger::Snap(int SnappingClient)
|
|||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
|
||||
CNetObj_EntityEx *pEntData = 0;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_SWITCH)
|
||||
int Subtype = (m_IgnoreWalls ? 1 : 0) | (clamp(round_to_int(m_Strength - 1.f), 0, 2) << 1);
|
||||
|
||||
int StartTick;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
|
||||
if(pEntData)
|
||||
{
|
||||
pEntData->m_SwitchNumber = m_Number;
|
||||
pEntData->m_Layer = m_Layer;
|
||||
pEntData->m_EntityClass = clamp(ENTITYCLASS_DRAGGER_WEAK + round_to_int(m_Strength) - 1,
|
||||
(int)ENTITYCLASS_DRAGGER_WEAK, (int)ENTITYCLASS_DRAGGER_STRONG);
|
||||
}
|
||||
StartTick = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -212,11 +207,7 @@ void CDragger::Snap(int SnappingClient)
|
|||
if(pChar && m_Layer == LAYER_SWITCH && m_Number > 0 &&
|
||||
!Switchers()[m_Number].m_aStatus[pChar->Team()] && !Tick)
|
||||
return;
|
||||
}
|
||||
|
||||
int StartTick = 0;
|
||||
if(!pEntData)
|
||||
{
|
||||
StartTick = m_EvalTick;
|
||||
if(StartTick < Server()->Tick() - 4)
|
||||
StartTick = Server()->Tick() - 4;
|
||||
|
@ -225,5 +216,5 @@ void CDragger::Snap(int SnappingClient)
|
|||
}
|
||||
|
||||
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
|
||||
m_Pos, m_Pos, StartTick, -1, LASERTYPE_DOOR);
|
||||
m_Pos, m_Pos, StartTick, -1, LASERTYPE_DRAGGER, Subtype, m_Number);
|
||||
}
|
||||
|
|
|
@ -109,6 +109,8 @@ void CDraggerBeam::Snap(int SnappingClient)
|
|||
return;
|
||||
}
|
||||
|
||||
int Subtype = (m_IgnoreWalls ? 1 : 0) | (clamp(round_to_int(m_Strength - 1.f), 0, 2) << 1);
|
||||
|
||||
int StartTick = m_EvalTick;
|
||||
if(StartTick < Server()->Tick() - 4)
|
||||
{
|
||||
|
@ -121,7 +123,7 @@ void CDraggerBeam::Snap(int SnappingClient)
|
|||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
|
||||
m_Pos, TargetPos, StartTick, -1, LASERTYPE_DOOR);
|
||||
m_Pos, TargetPos, StartTick, -1, LASERTYPE_DRAGGER, Subtype, m_Number);
|
||||
}
|
||||
|
||||
void CDraggerBeam::SwapClients(int Client1, int Client2)
|
||||
|
|
|
@ -149,25 +149,12 @@ void CGun::Snap(int SnappingClient)
|
|||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
|
||||
CNetObj_EntityEx *pEntData = 0;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_SWITCH)
|
||||
{
|
||||
pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(),
|
||||
sizeof(CNetObj_EntityEx)));
|
||||
if(pEntData)
|
||||
{
|
||||
pEntData->m_SwitchNumber = m_Number;
|
||||
pEntData->m_Layer = m_Layer;
|
||||
int Subtype = (m_Explosive ? 1 : 0) | (m_Freeze ? 2 : 0);
|
||||
|
||||
if(m_Explosive && !m_Freeze)
|
||||
pEntData->m_EntityClass = ENTITYCLASS_GUN_NORMAL;
|
||||
else if(m_Explosive && m_Freeze)
|
||||
pEntData->m_EntityClass = ENTITYCLASS_GUN_EXPLOSIVE;
|
||||
else if(!m_Explosive && m_Freeze)
|
||||
pEntData->m_EntityClass = ENTITYCLASS_GUN_FREEZE;
|
||||
else
|
||||
pEntData->m_EntityClass = ENTITYCLASS_GUN_UNFREEZE;
|
||||
}
|
||||
int StartTick;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
StartTick = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -184,10 +171,10 @@ void CGun::Snap(int SnappingClient)
|
|||
if(pChar && m_Layer == LAYER_SWITCH && m_Number > 0 &&
|
||||
!Switchers()[m_Number].m_aStatus[pChar->Team()] && (!Tick))
|
||||
return;
|
||||
|
||||
StartTick = m_EvalTick;
|
||||
}
|
||||
|
||||
int StartTick = pEntData ? 0 : m_EvalTick;
|
||||
|
||||
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
|
||||
m_Pos, m_Pos, StartTick, -1, m_Freeze ? LASERTYPE_FREEZE : LASERTYPE_RIFLE);
|
||||
m_Pos, m_Pos, StartTick, -1, LASERTYPE_GUN, Subtype, m_Number);
|
||||
}
|
||||
|
|
|
@ -316,8 +316,9 @@ void CLaser::Snap(int SnappingClient)
|
|||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
int LaserType = m_Type == WEAPON_LASER ? LASERTYPE_RIFLE : m_Type == WEAPON_SHOTGUN ? LASERTYPE_SHOTGUN : -1;
|
||||
|
||||
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
|
||||
m_Pos, m_From, m_EvalTick, m_Owner, LaserType);
|
||||
m_Pos, m_From, m_EvalTick, m_Owner, LaserType, 0, m_Number);
|
||||
}
|
||||
|
||||
void CLaser::SwapClients(int Client1, int Client2)
|
||||
|
|
|
@ -107,28 +107,11 @@ void CLight::Snap(int SnappingClient)
|
|||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
|
||||
CNetObj_EntityEx *pEntData = 0;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_SWITCH && (m_Layer == LAYER_SWITCH || length(m_Core) > 0))
|
||||
pEntData = static_cast<CNetObj_EntityEx *>(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx)));
|
||||
|
||||
CCharacter *pChr = GameServer()->GetPlayerChar(SnappingClient);
|
||||
|
||||
if(SnappingClient != SERVER_DEMO_CLIENT && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == TEAM_SPECTATORS || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
|
||||
pChr = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
|
||||
|
||||
if(pEntData)
|
||||
{
|
||||
pEntData->m_SwitchNumber = m_Number;
|
||||
pEntData->m_Layer = m_Layer;
|
||||
pEntData->m_EntityClass = ENTITYCLASS_LIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 6;
|
||||
if(pChr && pChr->IsAlive() && m_Layer == LAYER_SWITCH && m_Number > 0 && !Switchers()[m_Number].m_aStatus[pChr->Team()] && Tick)
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 From = m_Pos;
|
||||
int StartTick = 0;
|
||||
|
||||
|
@ -145,8 +128,12 @@ void CLight::Snap(int SnappingClient)
|
|||
From = m_To;
|
||||
}
|
||||
|
||||
if(!pEntData)
|
||||
if(SnappingClientVersion < VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 6;
|
||||
if(pChr && pChr->IsAlive() && m_Layer == LAYER_SWITCH && m_Number > 0 && !Switchers()[m_Number].m_aStatus[pChr->Team()] && Tick)
|
||||
return;
|
||||
|
||||
StartTick = m_EvalTick;
|
||||
if(StartTick < Server()->Tick() - 4)
|
||||
StartTick = Server()->Tick() - 4;
|
||||
|
@ -155,5 +142,5 @@ void CLight::Snap(int SnappingClient)
|
|||
}
|
||||
|
||||
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
|
||||
m_Pos, From, StartTick, -1, LASERTYPE_FREEZE);
|
||||
m_Pos, From, StartTick, -1, LASERTYPE_FREEZE, 0, m_Number);
|
||||
}
|
||||
|
|
|
@ -167,32 +167,22 @@ void CPickup::Snap(int SnappingClient)
|
|||
if(NetworkClipped(SnappingClient))
|
||||
return;
|
||||
|
||||
CCharacter *pChar = GameServer()->GetPlayerChar(SnappingClient);
|
||||
|
||||
if(SnappingClient != SERVER_DEMO_CLIENT && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == TEAM_SPECTATORS || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
|
||||
pChar = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
|
||||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
bool Sixup = Server()->IsSixup(SnappingClient);
|
||||
|
||||
CNetObj_EntityEx *pEntData = 0;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_SWITCH && (m_Layer == LAYER_SWITCH || length(m_Core) > 0))
|
||||
pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
|
||||
if(SnappingClientVersion < VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
CCharacter *pChar = GameServer()->GetPlayerChar(SnappingClient);
|
||||
|
||||
if(SnappingClient != SERVER_DEMO_CLIENT && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == TEAM_SPECTATORS || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW)
|
||||
pChar = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID);
|
||||
|
||||
if(pEntData)
|
||||
{
|
||||
pEntData->m_SwitchNumber = m_Number;
|
||||
pEntData->m_Layer = m_Layer;
|
||||
pEntData->m_EntityClass = ENTITYCLASS_PICKUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11;
|
||||
if(pChar && pChar->IsAlive() && m_Layer == LAYER_SWITCH && m_Number > 0 && !Switchers()[m_Number].m_aStatus[pChar->Team()] && !Tick)
|
||||
return;
|
||||
}
|
||||
|
||||
GameServer()->SnapPickup(CSnapContext(SnappingClientVersion, Sixup), GetID(), m_Pos, m_Type, m_Subtype);
|
||||
GameServer()->SnapPickup(CSnapContext(SnappingClientVersion, Sixup), GetID(), m_Pos, m_Type, m_Subtype, m_Number);
|
||||
}
|
||||
|
||||
void CPickup::Move()
|
||||
|
|
|
@ -119,8 +119,10 @@ void CPlasma::Snap(int SnappingClient)
|
|||
return;
|
||||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
|
||||
int Subtype = (m_Explosive ? 1 : 0) | (m_Freeze ? 2 : 0);
|
||||
GameServer()->SnapLaserObject(CSnapContext(SnappingClientVersion), GetID(),
|
||||
m_Pos, m_Pos, m_EvalTick, -1, m_Freeze ? LASERTYPE_FREEZE : LASERTYPE_RIFLE);
|
||||
m_Pos, m_Pos, m_EvalTick, -1, LASERTYPE_PLASMA, Subtype, m_Number);
|
||||
}
|
||||
|
||||
void CPlasma::SwapClients(int Client1, int Client2)
|
||||
|
|
|
@ -21,6 +21,7 @@ CProjectile::CProjectile(
|
|||
bool Freeze,
|
||||
bool Explosive,
|
||||
int SoundImpact,
|
||||
vec2 InitDir,
|
||||
int Layer,
|
||||
int Number) :
|
||||
CEntity(pGameWorld, CGameWorld::ENTTYPE_PROJECTILE)
|
||||
|
@ -39,6 +40,7 @@ CProjectile::CProjectile(
|
|||
m_Number = Number;
|
||||
m_Freeze = Freeze;
|
||||
|
||||
m_InitDir = InitDir;
|
||||
m_TuneZone = GameServer()->Collision()->IsTune(GameServer()->Collision()->GetMapIndex(m_Pos));
|
||||
|
||||
CCharacter *pOwnerChar = GameServer()->GetPlayerChar(m_Owner);
|
||||
|
@ -305,19 +307,8 @@ void CProjectile::Snap(int SnappingClient)
|
|||
if(NetworkClipped(SnappingClient, GetPos(Ct)))
|
||||
return;
|
||||
|
||||
if(m_LifeSpan == -2)
|
||||
{
|
||||
CNetObj_EntityEx *pEntData = Server()->SnapNewItem<CNetObj_EntityEx>(GetID());
|
||||
if(!pEntData)
|
||||
return;
|
||||
|
||||
pEntData->m_SwitchNumber = m_Number;
|
||||
pEntData->m_Layer = m_Layer;
|
||||
pEntData->m_EntityClass = ENTITYCLASS_PROJECTILE;
|
||||
}
|
||||
|
||||
int SnappingClientVersion = GameServer()->GetClientVersion(SnappingClient);
|
||||
if(SnappingClientVersion < VERSION_DDNET_SWITCH)
|
||||
if(SnappingClientVersion < VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
CCharacter *pSnapChar = GameServer()->GetPlayerChar(SnappingClient);
|
||||
int Tick = (Server()->Tick() % Server()->TickSpeed()) % ((m_Explosive) ? 6 : 20);
|
||||
|
@ -337,16 +328,26 @@ void CProjectile::Snap(int SnappingClient)
|
|||
if(SnappingClient != SERVER_DEMO_CLIENT && m_Owner != -1 && !TeamMask.test(SnappingClient))
|
||||
return;
|
||||
|
||||
CNetObj_DDNetProjectile DDNetProjectile;
|
||||
if(SnappingClientVersion >= VERSION_DDNET_ANTIPING_PROJECTILE && FillExtraInfo(&DDNetProjectile))
|
||||
CNetObj_DDRaceProjectile DDRaceProjectile;
|
||||
|
||||
if(SnappingClientVersion >= VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
int Type = SnappingClientVersion < VERSION_DDNET_MSG_LEGACY ? (int)NETOBJTYPE_PROJECTILE : NETOBJTYPE_DDNETPROJECTILE;
|
||||
void *pProj = Server()->SnapNewItem(Type, GetID(), sizeof(DDNetProjectile));
|
||||
CNetObj_DDNetProjectile *pDDNetProjectile = static_cast<CNetObj_DDNetProjectile *>(Server()->SnapNewItem(NETOBJTYPE_DDNETPROJECTILE, GetID(), sizeof(CNetObj_DDNetProjectile)));
|
||||
if(!pDDNetProjectile)
|
||||
{
|
||||
return;
|
||||
}
|
||||
FillExtraInfo(pDDNetProjectile);
|
||||
}
|
||||
else if(SnappingClientVersion >= VERSION_DDNET_ANTIPING_PROJECTILE && FillExtraInfoLegacy(&DDRaceProjectile))
|
||||
{
|
||||
int Type = SnappingClientVersion < VERSION_DDNET_MSG_LEGACY ? (int)NETOBJTYPE_PROJECTILE : NETOBJTYPE_DDRACEPROJECTILE;
|
||||
void *pProj = Server()->SnapNewItem(Type, GetID(), sizeof(DDRaceProjectile));
|
||||
if(!pProj)
|
||||
{
|
||||
return;
|
||||
}
|
||||
mem_copy(pProj, &DDNetProjectile, sizeof(DDNetProjectile));
|
||||
mem_copy(pProj, &DDRaceProjectile, sizeof(DDRaceProjectile));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -371,7 +372,7 @@ void CProjectile::SetBouncing(int Value)
|
|||
m_Bouncing = Value;
|
||||
}
|
||||
|
||||
bool CProjectile::FillExtraInfo(CNetObj_DDNetProjectile *pProj)
|
||||
bool CProjectile::FillExtraInfoLegacy(CNetObj_DDRaceProjectile *pProj)
|
||||
{
|
||||
const int MaxPos = 0x7fffffff / 100;
|
||||
if(absolute((int)m_Pos.y) + 1 >= MaxPos || absolute((int)m_Pos.x) + 1 >= MaxPos)
|
||||
|
@ -385,15 +386,15 @@ bool CProjectile::FillExtraInfo(CNetObj_DDNetProjectile *pProj)
|
|||
int Data = 0;
|
||||
Data |= (absolute(m_Owner) & 255) << 0;
|
||||
if(m_Owner < 0)
|
||||
Data |= PROJECTILEFLAG_NO_OWNER;
|
||||
Data |= LEGACYPROJECTILEFLAG_NO_OWNER;
|
||||
//This bit tells the client to use the extra info
|
||||
Data |= PROJECTILEFLAG_IS_DDNET;
|
||||
// PROJECTILEFLAG_BOUNCE_HORIZONTAL, PROJECTILEFLAG_BOUNCE_VERTICAL
|
||||
Data |= LEGACYPROJECTILEFLAG_IS_DDNET;
|
||||
// LEGACYPROJECTILEFLAG_BOUNCE_HORIZONTAL, LEGACYPROJECTILEFLAG_BOUNCE_VERTICAL
|
||||
Data |= (m_Bouncing & 3) << 10;
|
||||
if(m_Explosive)
|
||||
Data |= PROJECTILEFLAG_EXPLOSIVE;
|
||||
Data |= LEGACYPROJECTILEFLAG_EXPLOSIVE;
|
||||
if(m_Freeze)
|
||||
Data |= PROJECTILEFLAG_FREEZE;
|
||||
Data |= LEGACYPROJECTILEFLAG_FREEZE;
|
||||
|
||||
pProj->m_X = (int)(m_Pos.x * 100.0f);
|
||||
pProj->m_Y = (int)(m_Pos.y * 100.0f);
|
||||
|
@ -403,3 +404,45 @@ bool CProjectile::FillExtraInfo(CNetObj_DDNetProjectile *pProj)
|
|||
pProj->m_Type = m_Type;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CProjectile::FillExtraInfo(CNetObj_DDNetProjectile *pProj)
|
||||
{
|
||||
int Flags = 0;
|
||||
if(m_Bouncing & 1)
|
||||
{
|
||||
Flags |= PROJECTILEFLAG_BOUNCE_HORIZONTAL;
|
||||
}
|
||||
if(m_Bouncing & 2)
|
||||
{
|
||||
Flags |= PROJECTILEFLAG_BOUNCE_VERTICAL;
|
||||
}
|
||||
if(m_Explosive)
|
||||
{
|
||||
Flags |= PROJECTILEFLAG_EXPLOSIVE;
|
||||
}
|
||||
if(m_Freeze)
|
||||
{
|
||||
Flags |= PROJECTILEFLAG_FREEZE;
|
||||
}
|
||||
|
||||
if(m_Owner < 0)
|
||||
{
|
||||
pProj->m_VelX = round_to_int(m_Direction.x * 1e6f);
|
||||
pProj->m_VelY = round_to_int(m_Direction.y * 1e6f);
|
||||
}
|
||||
else
|
||||
{
|
||||
pProj->m_VelX = round_to_int(m_InitDir.x);
|
||||
pProj->m_VelY = round_to_int(m_InitDir.y);
|
||||
Flags |= PROJECTILEFLAG_NORMALIZE_VEL;
|
||||
}
|
||||
|
||||
pProj->m_X = round_to_int(m_Pos.x * 100.0f);
|
||||
pProj->m_Y = round_to_int(m_Pos.y * 100.0f);
|
||||
pProj->m_Type = m_Type;
|
||||
pProj->m_StartTick = m_StartTick;
|
||||
pProj->m_Owner = m_Owner;
|
||||
pProj->m_Flags = Flags;
|
||||
pProj->m_SwitchNumber = m_Number;
|
||||
pProj->m_TuneZone = m_TuneZone;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ public:
|
|||
bool Freeze,
|
||||
bool Explosive,
|
||||
int SoundImpact,
|
||||
vec2 InitDir,
|
||||
int Layer = 0,
|
||||
int Number = 0);
|
||||
|
||||
|
@ -46,10 +47,12 @@ private:
|
|||
bool m_Freeze;
|
||||
int m_TuneZone;
|
||||
bool m_BelongsToPracticeTeam;
|
||||
vec2 m_InitDir;
|
||||
|
||||
public:
|
||||
void SetBouncing(int Value);
|
||||
bool FillExtraInfo(CNetObj_DDNetProjectile *pProj);
|
||||
bool FillExtraInfoLegacy(CNetObj_DDRaceProjectile *pProj);
|
||||
void FillExtraInfo(CNetObj_DDNetProjectile *pProj);
|
||||
|
||||
virtual int GetOwnerID() const override { return m_Owner; }
|
||||
};
|
||||
|
|
|
@ -373,7 +373,7 @@ void CGameContext::CreateSoundGlobal(int Sound, int Target)
|
|||
}
|
||||
}
|
||||
|
||||
bool CGameContext::SnapLaserObject(const CSnapContext &Context, int SnapID, const vec2 &To, const vec2 &From, int StartTick, int Owner, int LaserType)
|
||||
bool CGameContext::SnapLaserObject(const CSnapContext &Context, int SnapID, const vec2 &To, const vec2 &From, int StartTick, int Owner, int LaserType, int Subtype, int SwitchNumber)
|
||||
{
|
||||
if(Context.GetClientVersion() >= VERSION_DDNET_MULTI_LASER)
|
||||
{
|
||||
|
@ -388,6 +388,8 @@ bool CGameContext::SnapLaserObject(const CSnapContext &Context, int SnapID, cons
|
|||
pObj->m_StartTick = StartTick;
|
||||
pObj->m_Owner = Owner;
|
||||
pObj->m_Type = LaserType;
|
||||
pObj->m_Subtype = Subtype;
|
||||
pObj->m_SwitchNumber = SwitchNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -405,7 +407,7 @@ bool CGameContext::SnapLaserObject(const CSnapContext &Context, int SnapID, cons
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CGameContext::SnapPickup(const CSnapContext &Context, int SnapID, const vec2 &Pos, int Type, int SubType)
|
||||
bool CGameContext::SnapPickup(const CSnapContext &Context, int SnapID, const vec2 &Pos, int Type, int SubType, int SwitchNumber)
|
||||
{
|
||||
if(Context.IsSixup())
|
||||
{
|
||||
|
@ -421,6 +423,18 @@ bool CGameContext::SnapPickup(const CSnapContext &Context, int SnapID, const vec
|
|||
else if(Type == POWERUP_NINJA)
|
||||
pPickup->m_Type = protocol7::PICKUP_NINJA;
|
||||
}
|
||||
else if(Context.GetClientVersion() >= VERSION_DDNET_ENTITY_NETOBJS)
|
||||
{
|
||||
CNetObj_DDNetPickup *pPickup = Server()->SnapNewItem<CNetObj_DDNetPickup>(SnapID);
|
||||
if(!pPickup)
|
||||
return false;
|
||||
|
||||
pPickup->m_X = (int)Pos.x;
|
||||
pPickup->m_Y = (int)Pos.y;
|
||||
pPickup->m_Type = Type;
|
||||
pPickup->m_Subtype = SubType;
|
||||
pPickup->m_SwitchNumber = SwitchNumber;
|
||||
}
|
||||
else
|
||||
{
|
||||
CNetObj_Pickup *pPickup = Server()->SnapNewItem<CNetObj_Pickup>(SnapID);
|
||||
|
|
|
@ -228,8 +228,8 @@ public:
|
|||
void CreateSound(vec2 Pos, int Sound, CClientMask Mask = CClientMask().set());
|
||||
void CreateSoundGlobal(int Sound, int Target = -1);
|
||||
|
||||
bool SnapLaserObject(const CSnapContext &Context, int SnapID, const vec2 &To, const vec2 &From, int StartTick, int Owner = -1, int LaserType = -1);
|
||||
bool SnapPickup(const CSnapContext &Context, int SnapID, const vec2 &Pos, int Type, int SubType);
|
||||
bool SnapLaserObject(const CSnapContext &Context, int SnapID, const vec2 &To, const vec2 &From, int StartTick, int Owner = -1, int LaserType = -1, int Subtype = -1, int SwitchNumber = -1);
|
||||
bool SnapPickup(const CSnapContext &Context, int SnapID, const vec2 &Pos, int Type, int SubType, int SwitchNumber);
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -232,6 +232,7 @@ bool IGameController::OnEntity(int Index, int x, int y, int Layer, int Flags, bo
|
|||
true, //Freeze
|
||||
true, //Explosive
|
||||
(g_Config.m_SvShotgunBulletSound) ? SOUND_GRENADE_EXPLODE : -1, //SoundImpact
|
||||
vec2(std::sin(Deg), std::cos(Deg)), // InitDir
|
||||
Layer,
|
||||
Number);
|
||||
pBullet->SetBouncing(2 - (Dir % 2));
|
||||
|
@ -258,6 +259,7 @@ bool IGameController::OnEntity(int Index, int x, int y, int Layer, int Flags, bo
|
|||
true, //Freeze
|
||||
false, //Explosive
|
||||
SOUND_GRENADE_EXPLODE,
|
||||
vec2(std::sin(Deg), std::cos(Deg)), // InitDir
|
||||
Layer,
|
||||
Number);
|
||||
pBullet->SetBouncing(2 - (Dir % 2));
|
||||
|
|
Loading…
Reference in a new issue