mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
Add Comments with Specifications to Turrets and Dragger
- Make Plasma Bullets explode only once if they hit a character and a obstacle - Make turrets fire speed independend from teams and solo players - Make draggers keep dragging the same tee, also if a closer tee exist
This commit is contained in:
parent
ab37f95bb4
commit
8fc34ae7b9
|
@ -23,6 +23,10 @@ CDragger::CDragger(CGameWorld *pGameWorld, vec2 Pos, float Strength, bool Ignore
|
|||
m_Number = Number;
|
||||
m_EvalTick = Server()->Tick();
|
||||
|
||||
for(auto &TargetId : m_TargetIdInTeam)
|
||||
{
|
||||
TargetId = -1;
|
||||
}
|
||||
mem_zero(m_apDraggerBeam, sizeof(m_apDraggerBeam));
|
||||
GameWorld()->InsertEntity(this);
|
||||
}
|
||||
|
@ -63,12 +67,14 @@ void CDragger::LookForPlayersToDrag()
|
|||
(CEntity **)pPlayersInRange, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
|
||||
|
||||
// The closest player (within range) in a team is selected as the target
|
||||
int TargetIdInTeam[MAX_CLIENTS];
|
||||
int ClosestTargetIdInTeam[MAX_CLIENTS];
|
||||
bool CanStillBeTeamTarget[MAX_CLIENTS];
|
||||
bool IsTarget[MAX_CLIENTS];
|
||||
int MinDistInTeam[MAX_CLIENTS];
|
||||
mem_zero(CanStillBeTeamTarget, sizeof(CanStillBeTeamTarget));
|
||||
mem_zero(MinDistInTeam, sizeof(MinDistInTeam));
|
||||
mem_zero(IsTarget, sizeof(IsTarget));
|
||||
for(int &TargetId : TargetIdInTeam)
|
||||
for(int &TargetId : ClosestTargetIdInTeam)
|
||||
{
|
||||
TargetId = -1;
|
||||
}
|
||||
|
@ -76,14 +82,16 @@ void CDragger::LookForPlayersToDrag()
|
|||
for(int i = 0; i < NumPlayersInRange; i++)
|
||||
{
|
||||
CCharacter *pTarget = pPlayersInRange[i];
|
||||
const int &TargetTeam = pTarget->Team();
|
||||
|
||||
// Do not create a dragger beam for super player
|
||||
if(pTarget->Team() == TEAM_SUPER)
|
||||
if(TargetTeam == TEAM_SUPER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// If the dragger is disabled for the target's team, no dragger beam will be generated
|
||||
if(m_Layer == LAYER_SWITCH && m_Number > 0 &&
|
||||
!GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[pTarget->Team()])
|
||||
!GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[TargetTeam])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -95,29 +103,35 @@ void CDragger::LookForPlayersToDrag()
|
|||
!GameServer()->Collision()->IntersectNoLaser(m_Pos, pTarget->m_Pos, 0, 0);
|
||||
if(IsReachable && pTarget->IsAlive())
|
||||
{
|
||||
const int &TargetClientId = pTarget->GetPlayer()->GetCID();
|
||||
// Solo players are dragged independently from the rest of the team
|
||||
if(pTarget->Teams()->m_Core.GetSolo(pTarget->GetPlayer()->GetCID()))
|
||||
if(pTarget->Teams()->m_Core.GetSolo(TargetClientId))
|
||||
{
|
||||
IsTarget[pTarget->GetPlayer()->GetCID()] = true;
|
||||
IsTarget[TargetClientId] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int Distance = distance(pTarget->m_Pos, m_Pos);
|
||||
if(MinDistInTeam[pTarget->Team()] == 0 || MinDistInTeam[pTarget->Team()] > Distance)
|
||||
if(MinDistInTeam[TargetTeam] == 0 || MinDistInTeam[TargetTeam] > Distance)
|
||||
{
|
||||
MinDistInTeam[pTarget->Team()] = Distance;
|
||||
TargetIdInTeam[pTarget->Team()] = pTarget->GetPlayer()->GetCID();
|
||||
MinDistInTeam[TargetTeam] = Distance;
|
||||
ClosestTargetIdInTeam[TargetTeam] = TargetClientId;
|
||||
}
|
||||
CanStillBeTeamTarget[TargetClientId] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the closest player for each team as a target
|
||||
for(int &TargetId : TargetIdInTeam)
|
||||
// Set the closest player for each team as a target if the team does not have a target player yet
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(TargetId != -1)
|
||||
if((m_TargetIdInTeam[i] != -1 && !CanStillBeTeamTarget[m_TargetIdInTeam[i]]) || m_TargetIdInTeam[i] == -1)
|
||||
{
|
||||
IsTarget[TargetId] = true;
|
||||
m_TargetIdInTeam[i] = ClosestTargetIdInTeam[i];
|
||||
}
|
||||
if(m_TargetIdInTeam[i] != -1)
|
||||
{
|
||||
IsTarget[m_TargetIdInTeam[i]] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,17 +5,33 @@
|
|||
#include <game/server/entity.h>
|
||||
class CDraggerBeam;
|
||||
|
||||
/**
|
||||
* Draggers generate dragger beams which pull players towards their center similar to a tractor beam
|
||||
*
|
||||
* A dragger will only generate one dragger beam per team for the closest player for whom the following criteria are met:
|
||||
* - The player is within the dragger range (m_SvDraggerRange).
|
||||
* - The player is not a super player
|
||||
* - The dragger is activated
|
||||
* - The dragger beam to be generated is not blocked by laser stoppers (or solid blocks if IgnoreWalls is set to false)
|
||||
* With the exception of solo players, for whom a dragger beam is always generated, regardless of the rest of the team,
|
||||
* if the above criteria are met. Solo players have no influence on the generation of the dragger beam for the rest
|
||||
* of the team.
|
||||
* A created dragger beam remains for the selected player until one of the criteria is no longer fulfilled. Only then
|
||||
* can a new dragger beam be created for that team, which may drag another team partner.
|
||||
*/
|
||||
class CDragger : public CEntity
|
||||
{
|
||||
// m_Core is the direction vector by which a dragger is shifted at each movement tick (every 150ms)
|
||||
vec2 m_Core;
|
||||
float m_Strength;
|
||||
int m_EvalTick;
|
||||
void LookForPlayersToDrag();
|
||||
bool m_IgnoreWalls;
|
||||
int m_EvalTick;
|
||||
|
||||
int m_TargetIdInTeam[MAX_CLIENTS];
|
||||
CDraggerBeam *m_apDraggerBeam[MAX_CLIENTS];
|
||||
|
||||
void LookForPlayersToDrag();
|
||||
|
||||
public:
|
||||
CDragger(CGameWorld *pGameWorld, vec2 Pos, float Strength, bool IgnoreWalls, int Layer = 0, int Number = 0);
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ void CDraggerBeam::Tick()
|
|||
Reset();
|
||||
return;
|
||||
}
|
||||
// In the center of the dragger a tee does not experience speed-up
|
||||
else if(distance(pTarget->m_Pos, m_Pos) > 28)
|
||||
{
|
||||
vec2 Temp = pTarget->Core()->m_Vel + (normalize(m_Pos - pTarget->m_Pos) * m_Strength);
|
||||
|
|
|
@ -5,6 +5,20 @@
|
|||
#include "dragger.h"
|
||||
#include <game/server/entity.h>
|
||||
|
||||
/**
|
||||
* Dragger beams pull a selected player towards their center
|
||||
*
|
||||
* Dragger beams are generated by a particular dragger for the player closest to it and for whom certain criteria are
|
||||
* met. Dragger beams exist until these criteria are no longer met. Dragger beams dissolve and automatically
|
||||
* de-register from their dragger source as soon as the player for whom they were created:
|
||||
* - is no longer alive
|
||||
* - is no longer in range (m_SvDraggerRange)
|
||||
* - can no longer be dragged because the beam is intercepted by a laser stopper (or if !IgnoreWalls by solid blocks)
|
||||
*
|
||||
* Dragger beams accelerate the selected player every tick towards their center. The length of the speed vector, which
|
||||
* is added to that of the player, depends only on the strength of the dragger and is between 1 and 3 units long. If
|
||||
* the player is in the center of the dragger, it will not accelerate.
|
||||
*/
|
||||
class CDraggerBeam : public CEntity
|
||||
{
|
||||
CDragger *m_pDragger;
|
||||
|
|
|
@ -19,9 +19,10 @@ CGun::CGun(CGameWorld *pGameWorld, vec2 Pos, bool Freeze, bool Explosive, int La
|
|||
m_Explosive = Explosive;
|
||||
m_Layer = Layer;
|
||||
m_Number = Number;
|
||||
m_LastFire = Server()->Tick();
|
||||
m_EvalTick = Server()->Tick();
|
||||
|
||||
mem_zero(m_LastFireTeam, sizeof(m_LastFireTeam));
|
||||
mem_zero(m_LastFireSolo, sizeof(m_LastFireSolo));
|
||||
GameWorld()->InsertEntity(this);
|
||||
}
|
||||
|
||||
|
@ -38,9 +39,10 @@ void CGun::Tick()
|
|||
}
|
||||
m_Pos += m_Core;
|
||||
}
|
||||
if(g_Config.m_SvPlasmaPerSec > 0 &&
|
||||
m_LastFire + Server()->TickSpeed() / g_Config.m_SvPlasmaPerSec <= Server()->Tick())
|
||||
if(g_Config.m_SvPlasmaPerSec != 0)
|
||||
{
|
||||
Fire();
|
||||
}
|
||||
}
|
||||
|
||||
void CGun::Fire()
|
||||
|
@ -66,14 +68,26 @@ void CGun::Fire()
|
|||
for(int i = 0; i < NumPlayersInRange; i++)
|
||||
{
|
||||
CCharacter *pTarget = pPlayersInRange[i];
|
||||
const int &TargetTeam = pTarget->Team();
|
||||
// Do not fire at super players
|
||||
if(pTarget->Team() == TEAM_SUPER)
|
||||
if(TargetTeam == TEAM_SUPER)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// If the turret is disabled for the target's team, the turret will not fire
|
||||
if(m_Layer == LAYER_SWITCH && m_Number > 0 &&
|
||||
!GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[pTarget->Team()])
|
||||
!GameServer()->Collision()->m_pSwitchers[m_Number].m_Status[TargetTeam])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Turrets can only shoot at a speed of m_SvPlasmaPerSec
|
||||
const int &TargetClientId = pTarget->GetPlayer()->GetCID();
|
||||
const bool &TargetIsSolo = pTarget->Teams()->m_Core.GetSolo(TargetClientId);
|
||||
if((TargetIsSolo &&
|
||||
m_LastFireSolo[TargetClientId] + Server()->TickSpeed() / g_Config.m_SvPlasmaPerSec > Server()->Tick()) ||
|
||||
(!TargetIsSolo &&
|
||||
m_LastFireTeam[TargetTeam] + Server()->TickSpeed() / g_Config.m_SvPlasmaPerSec > Server()->Tick()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -83,28 +97,30 @@ void CGun::Fire()
|
|||
if(IsReachable && pTarget->IsAlive())
|
||||
{
|
||||
// Turrets fire on solo players regardless of the rest of the team
|
||||
if(pTarget->Teams()->m_Core.GetSolo(pTarget->GetPlayer()->GetCID()))
|
||||
if(TargetIsSolo)
|
||||
{
|
||||
IsTarget[pTarget->GetPlayer()->GetCID()] = true;
|
||||
IsTarget[TargetClientId] = true;
|
||||
m_LastFireSolo[TargetClientId] = Server()->Tick();
|
||||
}
|
||||
else
|
||||
{
|
||||
int Distance = distance(pTarget->m_Pos, m_Pos);
|
||||
if(MinDistInTeam[pTarget->Team()] == 0 || MinDistInTeam[pTarget->Team()] > Distance)
|
||||
if(MinDistInTeam[TargetTeam] == 0 || MinDistInTeam[TargetTeam] > Distance)
|
||||
{
|
||||
MinDistInTeam[pTarget->Team()] = Distance;
|
||||
TargetIdInTeam[pTarget->Team()] = pTarget->GetPlayer()->GetCID();
|
||||
MinDistInTeam[TargetTeam] = Distance;
|
||||
TargetIdInTeam[TargetTeam] = TargetClientId;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the closest player for each team as a target
|
||||
for(int &TargetId : TargetIdInTeam)
|
||||
for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
{
|
||||
if(TargetId != -1)
|
||||
if(TargetIdInTeam[i] != -1)
|
||||
{
|
||||
IsTarget[TargetId] = true;
|
||||
IsTarget[TargetIdInTeam[i]] = true;
|
||||
m_LastFireTeam[i] = Server()->Tick();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +131,6 @@ void CGun::Fire()
|
|||
{
|
||||
CCharacter *pTarget = GameServer()->GetPlayerChar(i);
|
||||
new CPlasma(&GameServer()->m_World, m_Pos, normalize(pTarget->m_Pos - m_Pos), m_Freeze, m_Explosive, i);
|
||||
m_LastFire = Server()->Tick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,16 +6,30 @@
|
|||
#include <game/gamecore.h>
|
||||
#include <game/server/entity.h>
|
||||
|
||||
/**
|
||||
* Turrets (also referred to as Gun) fire plasma bullets at the nearest player
|
||||
*
|
||||
* A turret fires plasma bullets with a certain firing rate (m_SvPlasmaPerSec) at the closest player of a team for whom
|
||||
* the following criteria are met:
|
||||
* - The player is within the turret range (m_SvPlasmaRange)
|
||||
* - The player is not a super player
|
||||
* - The turret is activated
|
||||
* - The initial trajectory of the plasma bullet to be generated would not be stopped by any solid block
|
||||
* With the exception of solo players, for whom plasma bullets will always be fired, regardless of the rest of the team,
|
||||
* if the above criteria are met. Solo players do not affect the generation of plasma bullets for the rest of the team.
|
||||
* The shooting rate of m_SvPlasmaPerSec is independent for each team and solo player and starts with the first tick
|
||||
* when a target player is selected.
|
||||
*/
|
||||
class CGun : public CEntity
|
||||
{
|
||||
int m_EvalTick;
|
||||
|
||||
vec2 m_Core;
|
||||
bool m_Freeze;
|
||||
bool m_Explosive;
|
||||
int m_EvalTick;
|
||||
int m_LastFireTeam[MAX_CLIENTS];
|
||||
int m_LastFireSolo[MAX_CLIENTS];
|
||||
|
||||
void Fire();
|
||||
int m_LastFire;
|
||||
|
||||
public:
|
||||
CGun(CGameWorld *pGameWorld, vec2 Pos, bool Freeze, bool Explosive, int Layer = 0, int Number = 0);
|
||||
|
|
|
@ -29,35 +29,35 @@ CPlasma::CPlasma(CGameWorld *pGameWorld, vec2 Pos, vec2 Dir, bool Freeze,
|
|||
|
||||
void CPlasma::Tick()
|
||||
{
|
||||
// A plasma ball has only a limited lifetime
|
||||
// A plasma bullet has only a limited lifetime
|
||||
if(m_LifeTime == 0)
|
||||
{
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
CCharacter *pTarget = GameServer()->GetPlayerChar(m_ForClientID);
|
||||
// Without a target, a plasma ball has no reason to live
|
||||
// Without a target, a plasma bullet has no reason to live
|
||||
if(!pTarget)
|
||||
{
|
||||
// This can allow you to make plasma balls disappear by disconnecting, but this is not a serious cheat
|
||||
Reset();
|
||||
return;
|
||||
}
|
||||
m_LifeTime--;
|
||||
Move();
|
||||
HitCharacter(pTarget);
|
||||
|
||||
// Check if the plasma ball is stopped by a solid block or a laser stopper
|
||||
int HasIntersection = GameServer()->Collision()->IntersectNoLaser(m_Pos, m_Pos + m_Core, 0, 0);
|
||||
if(HasIntersection)
|
||||
if(!HitCharacter(pTarget))
|
||||
{
|
||||
if(m_Explosive)
|
||||
// Check if the plasma bullet is stopped by a solid block or a laser stopper
|
||||
int HasIntersection = GameServer()->Collision()->IntersectNoLaser(m_Pos, m_Pos + m_Core, 0, 0);
|
||||
if(HasIntersection)
|
||||
{
|
||||
// Even in the case of an explosion due to a collision with obstacles, only one player is affected
|
||||
GameServer()->CreateExplosion(
|
||||
m_Pos, m_ForClientID, WEAPON_GRENADE, true, pTarget->Team(), pTarget->TeamMask());
|
||||
if(m_Explosive)
|
||||
{
|
||||
// Even in the case of an explosion due to a collision with obstacles, only one player is affected
|
||||
GameServer()->CreateExplosion(
|
||||
m_Pos, m_ForClientID, WEAPON_GRENADE, true, pTarget->Team(), pTarget->TeamMask());
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,7 +77,7 @@ bool CPlasma::HitCharacter(CCharacter *pTarget)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Super player should not be able to stop the plasma balls
|
||||
// Super player should not be able to stop the plasma bullets
|
||||
if(HitPlayer->Team() == TEAM_SUPER)
|
||||
{
|
||||
return false;
|
||||
|
@ -91,7 +91,7 @@ bool CPlasma::HitCharacter(CCharacter *pTarget)
|
|||
GameServer()->CreateExplosion(
|
||||
m_Pos, m_ForClientID, WEAPON_GRENADE, true, pTarget->Team(), pTarget->TeamMask());
|
||||
}
|
||||
m_MarkedForDestroy = true;
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -102,14 +102,14 @@ void CPlasma::Reset()
|
|||
|
||||
void CPlasma::Snap(int SnappingClient)
|
||||
{
|
||||
// Only players who can see the targeted player can see the plasma ball
|
||||
// Only players who can see the targeted player can see the plasma bullet
|
||||
CCharacter *pTarget = GameServer()->GetPlayerChar(m_ForClientID);
|
||||
if(!pTarget->CanSnapCharacter(SnappingClient))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Only players with the plasma ball in their field of view or who want to see everything will receive the snap
|
||||
// Only players with the plasma bullet in their field of view or who want to see everything will receive the snap
|
||||
if(NetworkClipped(SnappingClient))
|
||||
return;
|
||||
|
||||
|
|
|
@ -4,6 +4,21 @@
|
|||
|
||||
#include <game/server/entity.h>
|
||||
|
||||
/**
|
||||
* Plasma Bullets are projectiles fired from turrets at a specific target
|
||||
*
|
||||
* When hitting a tee, plasma bullets can either freeze or unfreeze the player
|
||||
* Also, plasma projectiles can explode on impact. However, the player affected by the explosion is not necessarily the
|
||||
* one the plasma collided with, but if the affected player is not a solo player, then the team-mate with the lowest
|
||||
* ClientId within the explosion range. Furthermore, the affected player does not feel the explosion at the point of
|
||||
* impact but at the last position of the plasma bullet. The same applies if a plasma bullet explodes due to a collision
|
||||
* with a laser stopper or a solid block
|
||||
* Plasma bullets move every tick in the assigned direction and then accelerate by the factor PLASMA_ACCEL
|
||||
* Plasma bullets will stop existing as soon as:
|
||||
* - The player they were created for do no longer exist
|
||||
* - They have had a collision with a player, a solid block or a laser stopper
|
||||
* - Their life time of 1.5 seconds has expired
|
||||
*/
|
||||
class CPlasma : public CEntity
|
||||
{
|
||||
vec2 m_Core;
|
||||
|
|
Loading…
Reference in a new issue