ddnet/src/game/server/entities/character.cpp

2399 lines
75 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. */
#include <new>
#include <antibot/antibot_data.h>
2010-05-29 07:25:38 +00:00
#include <engine/shared/config.h>
#include <game/server/gamecontext.h>
#include <game/mapitems.h>
2010-05-29 07:25:38 +00:00
#include "character.h"
#include "laser.h"
#include "projectile.h"
#include <game/server/gamemodes/DDRace.h>
#include <game/server/score.h>
#include "light.h"
2010-05-29 07:25:38 +00:00
MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS)
2011-01-29 00:59:50 +00:00
// Character, "physical" player's part
2010-05-29 07:25:38 +00:00
CCharacter::CCharacter(CGameWorld *pWorld)
: CEntity(pWorld, CGameWorld::ENTTYPE_CHARACTER)
2008-09-23 07:43:41 +00:00
{
2010-06-03 15:39:42 +00:00
m_ProximityRadius = ms_PhysSize;
2010-05-29 07:25:38 +00:00
m_Health = 0;
m_Armor = 0;
2019-05-01 22:34:20 +00:00
m_StrongWeakID = 0;
2008-09-23 07:43:41 +00:00
}
2010-05-29 07:25:38 +00:00
void CCharacter::Reset()
{
2010-05-29 07:25:38 +00:00
Destroy();
}
2010-05-29 07:25:38 +00:00
bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
{
2010-05-29 07:25:38 +00:00
m_EmoteStop = -1;
m_LastAction = -1;
m_LastNoAmmoSound = -1;
2010-05-29 07:25:38 +00:00
m_LastWeapon = WEAPON_HAMMER;
m_QueuedWeapon = -1;
m_LastRefillJumps = false;
2014-02-09 22:31:29 +00:00
m_LastPenalty = false;
m_LastBonus = false;
2015-07-09 00:08:14 +00:00
2018-07-15 21:03:30 +00:00
m_TeleGunTeleport = false;
2018-11-02 23:02:20 +00:00
m_IsBlueTeleGunTeleport = false;
m_Solo = false;
2018-02-14 15:27:26 +00:00
2010-05-29 07:25:38 +00:00
m_pPlayer = pPlayer;
m_Pos = Pos;
mem_zero(&m_LatestPrevPrevInput, sizeof(m_LatestPrevPrevInput));
m_SpawnTick = Server()->Tick();
m_WeaponChangeTick = Server()->Tick();
Antibot()->OnSpawn(m_pPlayer->GetCID());
2010-05-29 07:25:38 +00:00
m_Core.Reset();
m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision(), &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core, &((CGameControllerDDRace*)GameServer()->m_pController)->m_TeleOuts);
2014-04-14 08:56:14 +00:00
m_Core.m_ActiveWeapon = WEAPON_GUN;
2010-05-29 07:25:38 +00:00
m_Core.m_Pos = m_Pos;
GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = &m_Core;
2011-01-29 00:59:50 +00:00
2010-05-29 07:25:38 +00:00
m_ReckoningTick = 0;
mem_zero(&m_SendCore, sizeof(m_SendCore));
mem_zero(&m_ReckoningCore, sizeof(m_ReckoningCore));
2010-05-29 07:25:38 +00:00
GameServer()->m_World.InsertEntity(this);
m_Alive = true;
2011-01-29 00:59:50 +00:00
2010-05-29 07:25:38 +00:00
GameServer()->m_pController->OnCharacterSpawn(this);
2011-01-29 00:59:50 +00:00
Teams()->OnCharacterSpawn(GetPlayer()->GetCID());
2011-01-29 00:59:50 +00:00
DDRaceInit();
2015-07-09 00:08:14 +00:00
2014-04-18 12:27:58 +00:00
m_TuneZone = GameServer()->Collision()->IsTune(GameServer()->Collision()->GetMapIndex(Pos));
m_TuneZoneOld = -1; // no zone leave msg on spawn
m_NeededFaketuning = 0; // reset fake tunings on respawn and send the client
2014-04-18 12:27:58 +00:00
SendZoneMsgs(); // we want a entermessage also on spawn
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone);
2011-01-29 00:59:50 +00:00
Server()->StartRecord(m_pPlayer->GetCID());
return true;
}
2010-05-29 07:25:38 +00:00
void CCharacter::Destroy()
{
2010-05-29 07:25:38 +00:00
GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
m_Alive = false;
m_Solo = false;
}
2010-05-29 07:25:38 +00:00
void CCharacter::SetWeapon(int W)
{
2014-04-14 08:56:14 +00:00
if(W == m_Core.m_ActiveWeapon)
return;
2014-04-14 08:56:14 +00:00
m_LastWeapon = m_Core.m_ActiveWeapon;
2010-05-29 07:25:38 +00:00
m_QueuedWeapon = -1;
m_Core.m_ActiveWeapon = W;
GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
2014-04-14 08:56:14 +00:00
if(m_Core.m_ActiveWeapon < 0 || m_Core.m_ActiveWeapon >= NUM_WEAPONS)
m_Core.m_ActiveWeapon = 0;
}
void CCharacter::SetSolo(bool Solo)
{
m_Solo = Solo;
2019-04-21 13:16:28 +00:00
m_Core.m_Solo = Solo;
Teams()->m_Core.SetSolo(m_pPlayer->GetCID(), Solo);
if(Solo)
m_NeededFaketuning |= FAKETUNE_SOLO;
else
m_NeededFaketuning &= ~FAKETUNE_SOLO;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
2010-05-29 07:25:38 +00:00
bool CCharacter::IsGrounded()
{
if(GameServer()->Collision()->CheckPoint(m_Pos.x+m_ProximityRadius/2, m_Pos.y+m_ProximityRadius/2+5))
return true;
if(GameServer()->Collision()->CheckPoint(m_Pos.x-m_ProximityRadius/2, m_Pos.y+m_ProximityRadius/2+5))
return true;
int MoveRestrictionsBelow = GameServer()->Collision()->GetMoveRestrictions(m_Pos + vec2(0, m_ProximityRadius / 2 + 4), 0.0f);
if(MoveRestrictionsBelow&CANTMOVE_DOWN)
{
return true;
}
return false;
}
2014-04-13 23:34:50 +00:00
void CCharacter::HandleJetpack()
{
vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
bool FullAuto = false;
if(m_Core.m_ActiveWeapon == WEAPON_GRENADE || m_Core.m_ActiveWeapon == WEAPON_SHOTGUN || m_Core.m_ActiveWeapon == WEAPON_LASER)
2014-04-13 23:34:50 +00:00
FullAuto = true;
2014-04-14 08:56:14 +00:00
if (m_Jetpack && m_Core.m_ActiveWeapon == WEAPON_GUN)
2014-04-13 23:34:50 +00:00
FullAuto = true;
// check if we gonna fire
bool WillFire = false;
if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses)
WillFire = true;
2014-04-14 08:56:14 +00:00
if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo)
2014-04-13 23:34:50 +00:00
WillFire = true;
if(!WillFire)
return;
// check for ammo
2020-03-17 12:55:30 +00:00
if(!m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo || m_FreezeTime)
2014-04-13 23:34:50 +00:00
{
return;
}
2014-04-14 08:56:14 +00:00
switch(m_Core.m_ActiveWeapon)
2014-04-13 23:34:50 +00:00
{
case WEAPON_GUN:
{
if (m_Jetpack)
{
float Strength;
if (!m_TuneZone)
Strength = GameServer()->Tuning()->m_JetpackStrength;
else
Strength = GameServer()->TuningList()[m_TuneZone].m_JetpackStrength;
2018-06-26 01:11:22 +00:00
TakeDamage(Direction * -1.0f * (Strength / 100.0f / 6.11f), 0, m_pPlayer->GetCID(), m_Core.m_ActiveWeapon);
2014-04-13 23:34:50 +00:00
}
}
}
}
2010-05-29 07:25:38 +00:00
void CCharacter::HandleNinja()
{
2014-04-14 08:56:14 +00:00
if(m_Core.m_ActiveWeapon != WEAPON_NINJA)
2010-05-29 07:25:38 +00:00
return;
2010-05-29 07:25:38 +00:00
if ((Server()->Tick() - m_Ninja.m_ActivationTick) > (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000))
{
// time's up, return
2016-10-08 17:42:42 +00:00
RemoveNinja();
2010-05-29 07:25:38 +00:00
return;
}
2013-12-09 12:53:26 +00:00
int NinjaTime = m_Ninja.m_ActivationTick + (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000) - Server()->Tick();
if (NinjaTime % Server()->TickSpeed() == 0 && NinjaTime / Server()->TickSpeed() <= 5)
{
GameServer()->CreateDamageInd(m_Pos, 0, NinjaTime / Server()->TickSpeed(), Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
}
m_Armor = 10 - (NinjaTime / 15);
2010-05-29 07:25:38 +00:00
// force ninja Weapon
SetWeapon(WEAPON_NINJA);
2010-05-29 07:25:38 +00:00
m_Ninja.m_CurrentMoveTime--;
2010-05-29 07:25:38 +00:00
if (m_Ninja.m_CurrentMoveTime == 0)
{
2010-05-29 07:25:38 +00:00
// reset velocity
m_Core.m_Vel = m_Ninja.m_ActivationDir*m_Ninja.m_OldVelAmount;
}
2010-05-29 07:25:38 +00:00
if (m_Ninja.m_CurrentMoveTime > 0)
{
2010-05-29 07:25:38 +00:00
// Set velocity
m_Core.m_Vel = m_Ninja.m_ActivationDir * g_pData->m_Weapons.m_Ninja.m_Velocity;
vec2 OldPos = m_Pos;
GameServer()->Collision()->MoveBox(&m_Core.m_Pos, &m_Core.m_Vel, vec2(m_ProximityRadius, m_ProximityRadius), 0.f);
// reset velocity so the client doesn't predict stuff
2010-05-29 07:25:38 +00:00
m_Core.m_Vel = vec2(0.f, 0.f);
2010-05-29 07:25:38 +00:00
// check if we Hit anything along the way
{
CCharacter *aEnts[MAX_CLIENTS];
2010-05-29 07:25:38 +00:00
vec2 Dir = m_Pos - OldPos;
2010-06-03 15:39:42 +00:00
float Radius = m_ProximityRadius * 2.0f;
2010-05-29 07:25:38 +00:00
vec2 Center = OldPos + Dir * 0.5f;
int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
2013-08-04 20:50:14 +00:00
// check that we're not in solo part
if (Teams()->m_Core.GetSolo(m_pPlayer->GetCID()))
return;
2010-05-29 07:25:38 +00:00
for (int i = 0; i < Num; ++i)
{
2010-05-29 07:25:38 +00:00
if (aEnts[i] == this)
continue;
2013-08-04 20:50:14 +00:00
// Don't hit players in other teams
if (Team() != aEnts[i]->Team())
continue;
// Don't hit players in solo parts
if (Teams()->m_Core.GetSolo(aEnts[i]->m_pPlayer->GetCID()))
return;
2010-05-29 07:25:38 +00:00
// make sure we haven't Hit this object before
bool bAlreadyHit = false;
for (int j = 0; j < m_NumObjectsHit; j++)
{
2010-05-29 07:25:38 +00:00
if (m_apHitObjects[j] == aEnts[i])
bAlreadyHit = true;
}
2010-05-29 07:25:38 +00:00
if (bAlreadyHit)
continue;
// check so we are sufficiently close
2010-06-03 15:39:42 +00:00
if (distance(aEnts[i]->m_Pos, m_Pos) > (m_ProximityRadius * 2.0f))
continue;
2011-01-29 00:59:50 +00:00
// Hit a player, give him damage and stuffs...
GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
// set his velocity to fast upward (for now)
2010-05-29 07:25:38 +00:00
if(m_NumObjectsHit < 10)
m_apHitObjects[m_NumObjectsHit++] = aEnts[i];
aEnts[i]->TakeDamage(vec2(0, -10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA);
}
}
2010-05-29 07:25:38 +00:00
return;
}
2010-05-29 07:25:38 +00:00
return;
}
2010-05-29 07:25:38 +00:00
void CCharacter::DoWeaponSwitch()
{
2010-05-29 07:25:38 +00:00
// make sure we can switch
if(m_ReloadTimer != 0 || m_QueuedWeapon == -1 || m_aWeapons[WEAPON_NINJA].m_Got || !m_aWeapons[m_QueuedWeapon].m_Got)
return;
2010-05-29 07:25:38 +00:00
// switch Weapon
SetWeapon(m_QueuedWeapon);
}
2010-05-29 07:25:38 +00:00
void CCharacter::HandleWeaponSwitch()
{
2014-04-14 08:56:14 +00:00
int WantedWeapon = m_Core.m_ActiveWeapon;
2010-05-29 07:25:38 +00:00
if(m_QueuedWeapon != -1)
WantedWeapon = m_QueuedWeapon;
bool Anything = false;
for(int i = 0; i < NUM_WEAPONS - 1; ++i)
if(m_aWeapons[i].m_Got)
Anything = true;
if(!Anything)
return;
2010-05-29 07:25:38 +00:00
// select Weapon
int Next = CountInput(m_LatestPrevInput.m_NextWeapon, m_LatestInput.m_NextWeapon).m_Presses;
int Prev = CountInput(m_LatestPrevInput.m_PrevWeapon, m_LatestInput.m_PrevWeapon).m_Presses;
2010-05-29 07:25:38 +00:00
if(Next < 128) // make sure we only try sane stuff
{
2010-05-29 07:25:38 +00:00
while(Next) // Next Weapon selection
{
2010-05-29 07:25:38 +00:00
WantedWeapon = (WantedWeapon+1)%NUM_WEAPONS;
if(m_aWeapons[WantedWeapon].m_Got)
Next--;
}
}
2010-05-29 07:25:38 +00:00
if(Prev < 128) // make sure we only try sane stuff
{
2010-05-29 07:25:38 +00:00
while(Prev) // Prev Weapon selection
{
2010-05-29 07:25:38 +00:00
WantedWeapon = (WantedWeapon-1)<0?NUM_WEAPONS-1:WantedWeapon-1;
if(m_aWeapons[WantedWeapon].m_Got)
Prev--;
}
}
2010-05-29 07:25:38 +00:00
// Direct Weapon selection
if(m_LatestInput.m_WantedWeapon)
WantedWeapon = m_Input.m_WantedWeapon-1;
// check for insane values
2014-04-14 08:56:14 +00:00
if(WantedWeapon >= 0 && WantedWeapon < NUM_WEAPONS && WantedWeapon != m_Core.m_ActiveWeapon && m_aWeapons[WantedWeapon].m_Got)
2010-05-29 07:25:38 +00:00
m_QueuedWeapon = WantedWeapon;
2010-05-29 07:25:38 +00:00
DoWeaponSwitch();
}
2010-05-29 07:25:38 +00:00
void CCharacter::FireWeapon()
{
2011-01-29 00:59:50 +00:00
if(m_ReloadTimer != 0)
{
if(m_LatestInput.m_Fire&1)
{
Antibot()->OnHammerFireReloading(m_pPlayer->GetCID());
}
return;
}
2010-05-29 07:25:38 +00:00
DoWeaponSwitch();
vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
2010-05-29 07:25:38 +00:00
bool FullAuto = false;
if(m_Core.m_ActiveWeapon == WEAPON_GRENADE || m_Core.m_ActiveWeapon == WEAPON_SHOTGUN || m_Core.m_ActiveWeapon == WEAPON_LASER)
2010-05-29 07:25:38 +00:00
FullAuto = true;
if(m_Jetpack && m_Core.m_ActiveWeapon == WEAPON_GUN)
2013-11-13 12:25:26 +00:00
FullAuto = true;
// allow firing directly after coming out of freeze or being unfrozen
// by something
if(m_FrozenLastTick)
2013-11-13 12:25:26 +00:00
FullAuto = true;
// don't fire hammer when player is deep and sv_deepfly is disabled
2019-10-16 05:08:44 +00:00
if(!g_Config.m_SvDeepfly && m_Core.m_ActiveWeapon == WEAPON_HAMMER && m_DeepFreeze)
return;
// check if we gonna fire
2010-05-29 07:25:38 +00:00
bool WillFire = false;
if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses)
WillFire = true;
2020-05-09 21:33:12 +00:00
if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo && !m_FreezeTime)
2010-05-29 07:25:38 +00:00
WillFire = true;
2010-05-29 07:25:38 +00:00
if(!WillFire)
return;
2020-03-16 10:52:53 +00:00
if (m_FreezeTime)
{
// Timer stuff to avoid shrieking orchestra caused by unfreeze-plasma
if(m_PainSoundTimer<=0)
{
m_PainSoundTimer = 1 * Server()->TickSpeed();
GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
}
return;
}
// check for ammo
2014-04-14 08:56:14 +00:00
if(!m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo)
{
/*// 125ms is a magical limit of how fast a human can click
2011-01-29 00:59:50 +00:00
m_ReloadTimer = 125 * Server()->TickSpeed() / 1000;
GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO);*/
return;
}
2010-06-03 15:39:42 +00:00
vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f;
2014-04-14 08:56:14 +00:00
switch(m_Core.m_ActiveWeapon)
{
case WEAPON_HAMMER:
{
2010-05-29 07:25:38 +00:00
// reset objects Hit
m_NumObjectsHit = 0;
GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
Antibot()->OnHammerFire(m_pPlayer->GetCID());
if (m_Hit&DISABLE_HIT_HAMMER) break;
CCharacter *apEnts[MAX_CLIENTS];
2010-05-29 07:25:38 +00:00
int Hits = 0;
int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts,
MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
2010-05-29 07:25:38 +00:00
for (int i = 0; i < Num; ++i)
{
2011-01-09 19:53:19 +00:00
CCharacter *pTarget = apEnts[i];
//if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL))
2014-09-22 16:56:59 +00:00
if((pTarget == this || (pTarget->IsAlive() && !CanCollide(pTarget->GetPlayer()->GetCID()))))
continue;
// set his velocity to fast upward (for now)
if(length(pTarget->m_Pos-ProjStartPos) > 0.0f)
GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*0.5f, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
else
GameServer()->CreateHammerHit(ProjStartPos, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
2010-05-29 07:25:38 +00:00
vec2 Dir;
2011-04-10 13:07:36 +00:00
if (length(pTarget->m_Pos - m_Pos) > 0.0f)
Dir = normalize(pTarget->m_Pos - m_Pos);
else
Dir = vec2(0.f, -1.f);
/*pTarget->TakeDamage(vec2(0.f, -1.f) + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage,
2014-04-14 08:56:14 +00:00
m_pPlayer->GetCID(), m_Core.m_ActiveWeapon);*/
2014-04-13 17:11:21 +00:00
float Strength;
if (!m_TuneZone)
Strength = GameServer()->Tuning()->m_HammerStrength;
else
Strength = GameServer()->TuningList()[m_TuneZone].m_HammerStrength;
vec2 Temp = pTarget->m_Core.m_Vel + normalize(Dir + vec2(0.f, -
1.1f)) * 10.0f;
Temp = ClampVel(pTarget->m_MoveRestrictions, Temp);
Temp -= pTarget->m_Core.m_Vel;
2014-04-13 17:11:21 +00:00
pTarget->TakeDamage((vec2(0.f, -1.0f) + Temp) * Strength, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage,
2014-04-14 08:56:14 +00:00
m_pPlayer->GetCID(), m_Core.m_ActiveWeapon);
pTarget->UnFreeze();
if(m_FreezeHammer)
pTarget->Freeze();
Antibot()->OnHammerHit(m_pPlayer->GetCID());
2010-05-29 07:25:38 +00:00
Hits++;
}
2010-05-29 07:25:38 +00:00
// if we Hit anything, we have to wait for the reload
if(Hits)
m_ReloadTimer = Server()->TickSpeed()/3;
} break;
case WEAPON_GUN:
{
2014-01-11 12:59:20 +00:00
if (!m_Jetpack || !m_pPlayer->m_NinjaJetpack)
2014-01-09 18:00:41 +00:00
{
int Lifetime;
if (!m_TuneZone)
Lifetime = (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime);
else
2014-04-13 14:49:58 +00:00
Lifetime = (int)(Server()->TickSpeed()*GameServer()->TuningList()[m_TuneZone].m_GunLifetime);
2015-07-09 00:08:14 +00:00
2014-01-09 18:00:41 +00:00
CProjectile *pProj = new CProjectile
(
GameWorld(),
WEAPON_GUN,//Type
m_pPlayer->GetCID(),//Owner
ProjStartPos,//Pos
Direction,//Dir
Lifetime,//Span
2014-01-09 18:00:41 +00:00
0,//Freeze
0,//Explosive
0,//Force
-1//SoundImpact
2014-01-09 18:00:41 +00:00
);
// pack the Projectile and send it to the client Directly
CNetObj_Projectile p;
pProj->FillInfo(&p);
2013-11-13 12:25:26 +00:00
2014-01-09 18:00:41 +00:00
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(1);
for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
Msg.AddInt(((int *)&p)[i]);
Server()->SendMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID());
GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
2014-01-09 18:00:41 +00:00
}
} break;
case WEAPON_SHOTGUN:
{
/*int ShotSpread = 2;
2010-05-29 07:25:38 +00:00
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(ShotSpread*2+1);
2010-05-29 07:25:38 +00:00
for(int i = -ShotSpread; i <= ShotSpread; ++i)
{
2010-05-29 07:25:38 +00:00
float Spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
float a = GetAngle(Direction);
a += Spreading[i+2];
float v = 1-(absolute(i)/(float)ShotSpread);
float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
2011-01-09 19:53:19 +00:00
CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
2010-05-29 07:25:38 +00:00
m_pPlayer->GetCID(),
ProjStartPos,
vec2(cosf(a), sinf(a))*Speed,
2011-01-29 00:59:50 +00:00
(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
1, 0, 0, -1);
2010-05-29 07:25:38 +00:00
// pack the Projectile and send it to the client Directly
CNetObj_Projectile p;
2011-01-09 19:53:19 +00:00
pProj->FillInfo(&p);
2010-05-29 07:25:38 +00:00
for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
Msg.AddInt(((int *)&p)[i]);
}
Server()->SendMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID());
GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE);*/
float LaserReach;
if (!m_TuneZone)
LaserReach = GameServer()->Tuning()->m_LaserReach;
else
2014-04-13 14:49:58 +00:00
LaserReach = GameServer()->TuningList()[m_TuneZone].m_LaserReach;
2015-07-09 00:08:14 +00:00
new CLaser(&GameServer()->m_World, m_Pos, Direction, LaserReach, m_pPlayer->GetCID(), WEAPON_SHOTGUN);
GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
} break;
case WEAPON_GRENADE:
{
int Lifetime;
if (!m_TuneZone)
Lifetime = (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GrenadeLifetime);
else
2014-04-13 14:49:58 +00:00
Lifetime = (int)(Server()->TickSpeed()*GameServer()->TuningList()[m_TuneZone].m_GrenadeLifetime);
2015-07-09 00:08:14 +00:00
2011-01-29 00:59:50 +00:00
CProjectile *pProj = new CProjectile
(
GameWorld(),
WEAPON_GRENADE,//Type
m_pPlayer->GetCID(),//Owner
ProjStartPos,//Pos
Direction,//Dir
Lifetime,//Span
0,//Freeze
true,//Explosive
0,//Force
SOUND_GRENADE_EXPLODE//SoundImpact
);//SoundImpact
2011-01-29 00:59:50 +00:00
// pack the Projectile and send it to the client Directly
CNetObj_Projectile p;
pProj->FillInfo(&p);
2011-01-29 00:59:50 +00:00
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(1);
for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
Msg.AddInt(((int *)&p)[i]);
Server()->SendMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID());
GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
} break;
case WEAPON_LASER:
{
float LaserReach;
if (!m_TuneZone)
LaserReach = GameServer()->Tuning()->m_LaserReach;
else
2014-04-13 14:49:58 +00:00
LaserReach = GameServer()->TuningList()[m_TuneZone].m_LaserReach;
2015-07-09 00:08:14 +00:00
new CLaser(GameWorld(), m_Pos, Direction, LaserReach, m_pPlayer->GetCID(), WEAPON_LASER);
GameServer()->CreateSound(m_Pos, SOUND_LASER_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
} break;
case WEAPON_NINJA:
{
2011-01-29 00:59:50 +00:00
// reset Hit objects
m_NumObjectsHit = 0;
2011-01-29 00:59:50 +00:00
m_Ninja.m_ActivationDir = Direction;
m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000;
m_Ninja.m_OldVelAmount = length(m_Core.m_Vel);
GameServer()->CreateSound(m_Pos, SOUND_NINJA_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
2011-01-29 00:59:50 +00:00
} break;
}
2010-05-29 07:25:38 +00:00
m_AttackTick = Server()->Tick();
2014-04-14 08:56:14 +00:00
/*if(m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited
m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo--;*/
2010-05-29 07:25:38 +00:00
if(!m_ReloadTimer)
2015-02-12 14:20:22 +00:00
{
float FireDelay;
if (!m_TuneZone)
GameServer()->Tuning()->Get(38 + m_Core.m_ActiveWeapon, &FireDelay);
else
GameServer()->TuningList()[m_TuneZone].Get(38 + m_Core.m_ActiveWeapon, &FireDelay);
m_ReloadTimer = FireDelay * Server()->TickSpeed() / 1000;
}
}
2010-05-29 07:25:38 +00:00
void CCharacter::HandleWeapons()
{
2010-05-29 07:25:38 +00:00
//ninja
HandleNinja();
2014-04-13 23:34:50 +00:00
HandleJetpack();
2011-01-29 00:59:50 +00:00
if(m_PainSoundTimer > 0)
m_PainSoundTimer--;
// check reload timer
2010-05-29 07:25:38 +00:00
if(m_ReloadTimer)
{
2010-05-29 07:25:38 +00:00
m_ReloadTimer--;
return;
}
2010-05-29 07:25:38 +00:00
// fire Weapon, if wanted
FireWeapon();
2011-01-29 00:59:50 +00:00
/*
// ammo regen
2014-04-14 08:56:14 +00:00
int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_Core.m_ActiveWeapon].m_Ammoregentime;
2010-05-29 07:25:38 +00:00
if(AmmoRegenTime)
{
// If equipped and not active, regen ammo?
2010-05-29 07:25:38 +00:00
if (m_ReloadTimer <= 0)
{
2014-04-14 08:56:14 +00:00
if (m_aWeapons[m_Core.m_ActiveWeapon].m_AmmoRegenStart < 0)
m_aWeapons[m_Core.m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick();
2014-04-14 08:56:14 +00:00
if ((Server()->Tick() - m_aWeapons[m_Core.m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000)
{
// Add some ammo
2019-04-26 19:36:49 +00:00
m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo = minimum(m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo + 1, 10);
2014-04-14 08:56:14 +00:00
m_aWeapons[m_Core.m_ActiveWeapon].m_AmmoRegenStart = -1;
}
}
else
{
2014-04-14 08:56:14 +00:00
m_aWeapons[m_Core.m_ActiveWeapon].m_AmmoRegenStart = -1;
}
}*/
2010-05-29 07:25:38 +00:00
return;
}
void CCharacter::GiveNinja()
{
m_Ninja.m_ActivationTick = Server()->Tick();
m_aWeapons[WEAPON_NINJA].m_Got = true;
2020-03-16 10:52:53 +00:00
m_aWeapons[WEAPON_NINJA].m_Ammo = -1;
2014-04-14 08:56:14 +00:00
if (m_Core.m_ActiveWeapon != WEAPON_NINJA)
m_LastWeapon = m_Core.m_ActiveWeapon;
m_Core.m_ActiveWeapon = WEAPON_NINJA;
2011-01-29 00:59:50 +00:00
if(!m_aWeapons[WEAPON_NINJA].m_Got)
GameServer()->CreateSound(m_Pos, SOUND_PICKUP_NINJA, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
}
2016-10-08 17:42:42 +00:00
void CCharacter::RemoveNinja()
{
m_Ninja.m_CurrentMoveTime = 0;
m_aWeapons[WEAPON_NINJA].m_Got = false;
m_Core.m_ActiveWeapon = m_LastWeapon;
2017-02-21 16:10:08 +00:00
2016-10-08 17:42:42 +00:00
SetWeapon(m_Core.m_ActiveWeapon);
}
2010-05-29 07:25:38 +00:00
void CCharacter::SetEmote(int Emote, int Tick)
{
m_EmoteType = Emote;
m_EmoteStop = Tick;
}
void CCharacter::OnPredictedInput(CNetObj_PlayerInput *pNewInput)
{
// check for changes
2016-08-27 15:06:52 +00:00
if(mem_comp(&m_SavedInput, pNewInput, sizeof(CNetObj_PlayerInput)) != 0)
2010-05-29 07:25:38 +00:00
m_LastAction = Server()->Tick();
// copy new input
2010-05-29 07:25:38 +00:00
mem_copy(&m_Input, pNewInput, sizeof(m_Input));
m_NumInputs++;
// it is not allowed to aim in the center
2010-05-29 07:25:38 +00:00
if(m_Input.m_TargetX == 0 && m_Input.m_TargetY == 0)
m_Input.m_TargetY = -1;
2017-08-25 11:27:37 +00:00
mem_copy(&m_SavedInput, &m_Input, sizeof(m_SavedInput));
}
2010-05-29 07:25:38 +00:00
void CCharacter::OnDirectInput(CNetObj_PlayerInput *pNewInput)
{
2010-05-29 07:25:38 +00:00
mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput));
mem_copy(&m_LatestInput, pNewInput, sizeof(m_LatestInput));
// it is not allowed to aim in the center
if(m_LatestInput.m_TargetX == 0 && m_LatestInput.m_TargetY == 0)
m_LatestInput.m_TargetY = -1;
Antibot()->OnDirectInput(m_pPlayer->GetCID());
2011-01-03 11:50:38 +00:00
if(m_NumInputs > 2 && m_pPlayer->GetTeam() != TEAM_SPECTATORS)
{
2010-05-29 07:25:38 +00:00
HandleWeaponSwitch();
FireWeapon();
}
mem_copy(&m_LatestPrevPrevInput, &m_LatestPrevInput, sizeof(m_LatestInput));
2010-05-29 07:25:38 +00:00
mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput));
}
void CCharacter::ResetInput()
{
m_Input.m_Direction = 0;
2014-01-22 13:04:46 +00:00
//m_Input.m_Hook = 0;
// simulate releasing the fire button
if((m_Input.m_Fire&1) != 0)
m_Input.m_Fire++;
m_Input.m_Fire &= INPUT_STATE_MASK;
m_Input.m_Jump = 0;
m_LatestPrevInput = m_LatestInput = m_Input;
}
2011-01-29 00:59:50 +00:00
void CCharacter::Tick()
{
2011-01-29 00:59:50 +00:00
/*if(m_pPlayer->m_ForceBalanced)
{
char Buf[128];
str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam()));
GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID());
2011-01-29 00:59:50 +00:00
m_pPlayer->m_ForceBalanced = false;
}*/
if(m_Paused)
return;
2011-01-29 00:59:50 +00:00
DDRaceTick();
2015-07-09 00:08:14 +00:00
2020-05-15 16:29:34 +00:00
Antibot()->OnCharacterTick(m_pPlayer->GetCID());
2011-01-29 00:59:50 +00:00
m_Core.m_Input = m_Input;
m_Core.Tick(true);
if(!m_PrevInput.m_Hook && m_Input.m_Hook
&& !(m_Core.m_TriggeredEvents&COREEVENT_HOOK_ATTACH_PLAYER))
{
Antibot()->OnHookAttach(m_pPlayer->GetCID(), false);
}
2011-01-29 00:59:50 +00:00
// handle Weapons
HandleWeapons();
DDRacePostCoreTick();
if(m_Core.m_TriggeredEvents&COREEVENT_HOOK_ATTACH_PLAYER)
{
if(m_Core.m_HookedPlayer != -1
&& GameServer()->m_apPlayers[m_Core.m_HookedPlayer]->GetTeam() != -1)
{
Antibot()->OnHookAttach(m_pPlayer->GetCID(), true);
}
}
2011-01-29 00:59:50 +00:00
// Previnput
m_PrevInput = m_Input;
2011-01-29 00:59:50 +00:00
m_PrevPos = m_Core.m_Pos;
return;
}
2011-01-29 00:59:50 +00:00
void CCharacter::TickDefered()
{
// advance the dummy
{
CWorldCore TempWorld;
m_ReckoningCore.Init(&TempWorld, GameServer()->Collision(), &Teams()->m_Core, &((CGameControllerDDRace*)GameServer()->m_pController)->m_TeleOuts);
m_ReckoningCore.m_Id = m_pPlayer->GetCID();
m_ReckoningCore.Tick(false);
m_ReckoningCore.Move();
2011-01-29 00:59:50 +00:00
m_ReckoningCore.Quantize();
}
2011-01-29 00:59:50 +00:00
//lastsentcore
vec2 StartPos = m_Core.m_Pos;
vec2 StartVel = m_Core.m_Vel;
bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
m_Core.m_Id = m_pPlayer->GetCID();
m_Core.Move();
2011-01-29 00:59:50 +00:00
bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
m_Core.Quantize();
bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
m_Pos = m_Core.m_Pos;
2011-01-29 00:59:50 +00:00
if(!StuckBefore && (StuckAfterMove || StuckAfterQuant))
{
// Hackish solution to get rid of strict-aliasing warning
union
{
2011-01-29 00:59:50 +00:00
float f;
unsigned u;
}StartPosX, StartPosY, StartVelX, StartVelY;
StartPosX.f = StartPos.x;
StartPosY.f = StartPos.y;
StartVelX.f = StartVel.x;
StartVelY.f = StartVel.y;
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x",
2011-01-29 00:59:50 +00:00
StuckBefore,
StuckAfterMove,
StuckAfterQuant,
StartPos.x, StartPos.y,
StartVel.x, StartVel.y,
StartPosX.u, StartPosY.u,
StartVelX.u, StartVelY.u);
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
}
int Events = m_Core.m_TriggeredEvents;
//int Mask = CmaskAllExceptOne(m_pPlayer->GetCID());
if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Teams()->TeamMask(Team(), m_pPlayer->GetCID()));
if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Teams()->TeamMask(Team(), m_pPlayer->GetCID(), m_pPlayer->GetCID()));
if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Teams()->TeamMask(Team(), m_pPlayer->GetCID(), m_pPlayer->GetCID()));
2011-01-29 00:59:50 +00:00
2011-01-29 00:59:50 +00:00
if(m_pPlayer->GetTeam() == TEAM_SPECTATORS)
{
m_Pos.x = m_Input.m_TargetX;
m_Pos.y = m_Input.m_TargetY;
}
2011-01-29 00:59:50 +00:00
// update the m_SendCore if needed
{
CNetObj_Character Predicted;
CNetObj_Character Current;
mem_zero(&Predicted, sizeof(Predicted));
mem_zero(&Current, sizeof(Current));
m_ReckoningCore.Write(&Predicted);
m_Core.Write(&Current);
// only allow dead reackoning for a top of 3 seconds
if(m_Core.m_pReset || m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0)
{
m_ReckoningTick = Server()->Tick();
m_SendCore = m_Core;
m_ReckoningCore = m_Core;
m_Core.m_pReset = false;
}
}
}
2012-01-09 23:49:31 +00:00
void CCharacter::TickPaused()
{
++m_AttackTick;
++m_DamageTakenTick;
++m_Ninja.m_ActivationTick;
++m_ReckoningTick;
if(m_LastAction != -1)
++m_LastAction;
2014-04-14 08:56:14 +00:00
if(m_aWeapons[m_Core.m_ActiveWeapon].m_AmmoRegenStart > -1)
++m_aWeapons[m_Core.m_ActiveWeapon].m_AmmoRegenStart;
2012-01-09 23:49:31 +00:00
if(m_EmoteStop > -1)
++m_EmoteStop;
}
2011-01-29 00:59:50 +00:00
bool CCharacter::IncreaseHealth(int Amount)
{
if(m_Health >= 10)
return false;
m_Health = clamp(m_Health+Amount, 0, 10);
return true;
}
bool CCharacter::IncreaseArmor(int Amount)
{
if(m_Armor >= 10)
return false;
m_Armor = clamp(m_Armor+Amount, 0, 10);
return true;
}
void CCharacter::Die(int Killer, int Weapon)
{
2014-09-26 00:25:53 +00:00
if(Server()->IsRecording(m_pPlayer->GetCID()))
Server()->StopRecord(m_pPlayer->GetCID());
2011-01-29 00:59:50 +00:00
int ModeSpecial = GameServer()->m_pController->OnCharacterDeath(this, GameServer()->m_apPlayers[Killer], Weapon);
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d",
Killer, Server()->ClientName(Killer),
m_pPlayer->GetCID(), Server()->ClientName(m_pPlayer->GetCID()), Weapon, ModeSpecial);
GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
// send the kill message
CNetMsg_Sv_KillMsg Msg;
Msg.m_Killer = Killer;
Msg.m_Victim = m_pPlayer->GetCID();
Msg.m_Weapon = Weapon;
Msg.m_ModeSpecial = ModeSpecial;
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
// a nice sound
GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
// this is to rate limit respawning to 3 secs
m_pPlayer->m_PreviousDieTick = m_pPlayer->m_DieTick;
2011-01-29 00:59:50 +00:00
m_pPlayer->m_DieTick = Server()->Tick();
2011-01-29 00:59:50 +00:00
m_Alive = false;
m_Solo = false;
2010-05-29 07:25:38 +00:00
GameServer()->m_World.RemoveEntity(this);
2011-01-29 00:59:50 +00:00
GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
GameServer()->CreateDeath(m_Pos, m_pPlayer->GetCID(), Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
Teams()->OnCharacterDeath(GetPlayer()->GetCID(), Weapon);
2011-01-29 00:59:50 +00:00
}
bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
{
/*m_Core.m_Vel += Force;
if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage)
return false;
2011-01-29 00:59:50 +00:00
// m_pPlayer only inflicts half damage on self
if(From == m_pPlayer->GetCID())
2019-04-26 19:36:49 +00:00
Dmg = maximum(1, Dmg/2);
2011-01-29 00:59:50 +00:00
m_DamageTaken++;
// create healthmod indicator
if(Server()->Tick() < m_DamageTakenTick+25)
{
// make sure that the damage indicators doesn't group together
GameServer()->CreateDamageInd(m_Pos, m_DamageTaken*0.25f, Dmg);
}
else
{
m_DamageTaken = 0;
GameServer()->CreateDamageInd(m_Pos, 0, Dmg);
}
if(Dmg)
{
if(m_Armor)
{
if(Dmg > 1)
{
m_Health--;
Dmg--;
}
2011-01-29 00:59:50 +00:00
if(Dmg > m_Armor)
{
Dmg -= m_Armor;
m_Armor = 0;
}
else
{
m_Armor -= Dmg;
Dmg = 0;
}
}
2011-01-29 00:59:50 +00:00
m_Health -= Dmg;
}
m_DamageTakenTick = Server()->Tick();
// do damage Hit sound
if(From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
{
2013-12-31 05:13:57 +00:00
int64_t Mask = CmaskOne(From);
for(int i = 0; i < MAX_CLIENTS; i++)
{
if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS && GameServer()->m_apPlayers[i]->m_SpectatorID == From)
Mask |= CmaskOne(i);
}
GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, Mask);
}
2011-01-29 00:59:50 +00:00
// check for death
if(m_Health <= 0)
{
Die(From, Weapon);
2011-01-29 00:59:50 +00:00
// set attacker's face to happy (taunt!)
if (From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
{
CCharacter *pChr = GameServer()->m_apPlayers[From]->GetCharacter();
if (pChr)
{
pChr->m_EmoteType = EMOTE_HAPPY;
pChr->m_EmoteStop = Server()->Tick() + Server()->TickSpeed();
}
}
2011-01-29 00:59:50 +00:00
return false;
}
if (Dmg > 2)
GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG);
else
GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_SHORT);*/
2018-06-26 01:11:22 +00:00
if (Dmg)
2014-01-09 18:50:37 +00:00
{
m_EmoteType = EMOTE_PAIN;
m_EmoteStop = Server()->Tick() + 500 * Server()->TickSpeed() / 1000;
}
2011-01-29 00:59:50 +00:00
vec2 Temp = m_Core.m_Vel + Force;
m_Core.m_Vel = ClampVel(m_MoveRestrictions, Temp);
2011-01-29 00:59:50 +00:00
return true;
}
void CCharacter::Snap(int SnappingClient)
{
2013-12-31 05:13:57 +00:00
int id = m_pPlayer->GetCID();
if(SnappingClient > -1 && !Server()->Translate(id, SnappingClient))
2013-12-31 05:13:57 +00:00
return;
2011-01-29 00:59:50 +00:00
if(NetworkClipped(SnappingClient))
return;
if(SnappingClient > -1)
{
CCharacter* SnapChar = GameServer()->GetPlayerChar(SnappingClient);
CPlayer* SnapPlayer = GameServer()->m_apPlayers[SnappingClient];
2017-04-08 22:20:41 +00:00
if((SnapPlayer->GetTeam() == TEAM_SPECTATORS || SnapPlayer->IsPaused()) && SnapPlayer->m_SpectatorID != -1
&& !CanCollide(SnapPlayer->m_SpectatorID) && !SnapPlayer->m_ShowOthers)
return;
2017-04-08 22:20:41 +00:00
if( SnapPlayer->GetTeam() != TEAM_SPECTATORS && !SnapPlayer->IsPaused() && SnapChar && !SnapChar->m_Super
&& !CanCollide(SnappingClient) && !SnapPlayer->m_ShowOthers)
return;
2017-04-08 22:20:41 +00:00
if((SnapPlayer->GetTeam() == TEAM_SPECTATORS || SnapPlayer->IsPaused()) && SnapPlayer->m_SpectatorID == -1
&& !CanCollide(SnappingClient) && SnapPlayer->m_SpecTeam)
return;
}
2014-08-09 17:53:38 +00:00
if (m_Paused)
return;
2013-12-31 05:13:57 +00:00
CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, id, sizeof(CNetObj_Character)));
2011-01-29 00:59:50 +00:00
if(!pCharacter)
return;
2011-01-29 00:59:50 +00:00
// write down the m_Core
if(!m_ReckoningTick || GameServer()->m_World.m_Paused)
{
// no dead reckoning when paused because the client doesn't know
// how far to perform the reckoning
pCharacter->m_Tick = 0;
m_Core.Write(pCharacter);
}
else
{
pCharacter->m_Tick = m_ReckoningTick;
m_SendCore.Write(pCharacter);
}
2011-01-29 00:59:50 +00:00
// set emote
if (m_EmoteStop < Server()->Tick())
{
Added the following settings to Close #123. sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands" sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time" sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands" Added the following Chat commands to give the player the choice over their settings: "saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race" "saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race" "time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message" "broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status" "servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status" Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect. So now players have the choice to see which timer they wanna see if any. Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
m_EmoteType = m_pPlayer->m_DefEmote;
2011-01-29 00:59:50 +00:00
m_EmoteStop = -1;
}
2015-03-14 17:55:50 +00:00
pCharacter->m_Emote = m_EmoteType;
2011-01-29 00:59:50 +00:00
2013-12-31 05:13:57 +00:00
if (pCharacter->m_HookedPlayer != -1)
{
if (!Server()->Translate(pCharacter->m_HookedPlayer, SnappingClient))
pCharacter->m_HookedPlayer = -1;
}
2011-01-29 00:59:50 +00:00
2015-03-14 17:55:50 +00:00
pCharacter->m_AttackTick = m_AttackTick;
pCharacter->m_Direction = m_Input.m_Direction;
pCharacter->m_Weapon = m_Core.m_ActiveWeapon;
2011-01-29 00:59:50 +00:00
pCharacter->m_AmmoCount = 0;
pCharacter->m_Health = 0;
pCharacter->m_Armor = 0;
2015-03-14 17:55:50 +00:00
// change eyes and use ninja graphic if player is freeze
if (m_DeepFreeze)
{
2011-08-14 15:23:57 +00:00
if (pCharacter->m_Emote == EMOTE_NORMAL)
pCharacter->m_Emote = EMOTE_PAIN;
pCharacter->m_Weapon = WEAPON_NINJA;
}
else if (m_FreezeTime > 0 || m_FreezeTime == -1)
2011-01-29 00:59:50 +00:00
{
2011-08-14 15:23:57 +00:00
if (pCharacter->m_Emote == EMOTE_NORMAL)
pCharacter->m_Emote = EMOTE_BLINK;
2011-01-29 00:59:50 +00:00
pCharacter->m_Weapon = WEAPON_NINJA;
}
2015-03-14 17:55:50 +00:00
// jetpack and ninjajetpack prediction
if (m_pPlayer->GetCID() == SnappingClient)
{
if (m_Jetpack && pCharacter->m_Weapon != WEAPON_NINJA)
{
if (!(m_NeededFaketuning & FAKETUNE_JETPACK))
{
m_NeededFaketuning |= FAKETUNE_JETPACK;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone);
}
}
else
{
if (m_NeededFaketuning & FAKETUNE_JETPACK)
{
m_NeededFaketuning &= ~FAKETUNE_JETPACK;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone);
}
}
}
// change eyes, use ninja graphic and set ammo count if player has ninjajetpack
if (m_pPlayer->m_NinjaJetpack && m_Jetpack && m_Core.m_ActiveWeapon == WEAPON_GUN && !m_DeepFreeze && !(m_FreezeTime > 0 || m_FreezeTime == -1))
2014-01-09 18:00:41 +00:00
{
2015-03-14 17:55:50 +00:00
if (pCharacter->m_Emote == EMOTE_NORMAL)
pCharacter->m_Emote = EMOTE_HAPPY;
2014-01-09 18:00:41 +00:00
pCharacter->m_Weapon = WEAPON_NINJA;
pCharacter->m_AmmoCount = 10;
}
2011-01-29 00:59:50 +00:00
if(m_pPlayer->GetCID() == SnappingClient || SnappingClient == -1 ||
(!g_Config.m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID))
2011-01-29 00:59:50 +00:00
{
pCharacter->m_Health = m_Health;
pCharacter->m_Armor = m_Armor;
2014-04-14 08:56:14 +00:00
if(m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo > 0)
//pCharacter->m_AmmoCount = m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo;
pCharacter->m_AmmoCount = (!m_FreezeTime)?m_aWeapons[m_Core.m_ActiveWeapon].m_Ammo:0;
2011-01-29 00:59:50 +00:00
}
2017-04-08 22:20:41 +00:00
if(GetPlayer()->m_Afk || GetPlayer()->IsPaused())
{
if(m_FreezeTime > 0 || m_FreezeTime == -1 || m_DeepFreeze)
pCharacter->m_Emote = EMOTE_NORMAL;
else
pCharacter->m_Emote = EMOTE_BLINK;
}
2014-01-22 00:46:15 +00:00
2011-01-29 00:59:50 +00:00
if(pCharacter->m_Emote == EMOTE_NORMAL)
{
if(250 - ((Server()->Tick() - m_LastAction)%(250)) < 5)
pCharacter->m_Emote = EMOTE_BLINK;
}
2014-09-18 10:14:00 +00:00
if(m_pPlayer->m_Halloween)
{
if(1200 - ((Server()->Tick() - m_LastAction)%(1200)) < 5)
{
GameServer()->SendEmoticon(m_pPlayer->GetCID(), EMOTICON_GHOST);
}
}
pCharacter->m_PlayerFlags = GetPlayer()->m_PlayerFlags;
CNetObj_DDNetCharacter *pDDNetCharacter = static_cast<CNetObj_DDNetCharacter *>(Server()->SnapNewItem(NETOBJTYPE_DDNETCHARACTER, id, sizeof(CNetObj_DDNetCharacter)));
2020-01-16 11:35:26 +00:00
if(!pDDNetCharacter)
return;
pDDNetCharacter->m_Flags = 0;
if(m_Solo)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_SOLO;
if(m_Super)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_SUPER;
if(m_EndlessHook)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_ENDLESS_HOOK;
if(!m_Core.m_Collision)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_COLLISION;
if(!m_Core.m_Hook)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_HOOK;
if(m_SuperJump)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_ENDLESS_JUMP;
if(m_Jetpack || m_NinjaJetpack)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_JETPACK;
if(m_Hit&DISABLE_HIT_GRENADE)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_GRENADE_HIT;
if(m_Hit&DISABLE_HIT_HAMMER)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_HAMMER_HIT;
if(m_Hit&DISABLE_HIT_LASER)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_LASER_HIT;
if(m_Hit&DISABLE_HIT_SHOTGUN)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_NO_SHOTGUN_HIT;
2019-08-19 08:09:53 +00:00
if(m_Core.m_HasTelegunGun)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_TELEGUN_GUN;
2019-08-19 08:09:53 +00:00
if(m_Core.m_HasTelegunGrenade)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_TELEGUN_GRENADE;
2019-08-19 08:09:53 +00:00
if(m_Core.m_HasTelegunLaser)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_TELEGUN_LASER;
2019-05-01 21:47:40 +00:00
if(m_aWeapons[WEAPON_HAMMER].m_Got)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_HAMMER;
if(m_aWeapons[WEAPON_GUN].m_Got)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_GUN;
if(m_aWeapons[WEAPON_SHOTGUN].m_Got)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_SHOTGUN;
if(m_aWeapons[WEAPON_GRENADE].m_Got)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_GRENADE;
if(m_aWeapons[WEAPON_LASER].m_Got)
2019-05-01 21:47:40 +00:00
pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_LASER;
if(m_Core.m_ActiveWeapon == WEAPON_NINJA)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_WEAPON_NINJA;
2019-06-30 21:47:51 +00:00
pDDNetCharacter->m_FreezeEnd = m_DeepFreeze ? -1 : m_FreezeTime == 0 ? 0 : Server()->Tick() + m_FreezeTime;
2019-05-01 21:47:40 +00:00
pDDNetCharacter->m_Jumps = m_Core.m_Jumps;
pDDNetCharacter->m_TeleCheckpoint = m_TeleCheckpoint;
2019-05-01 22:34:20 +00:00
pDDNetCharacter->m_StrongWeakID = m_StrongWeakID;
2011-01-29 00:59:50 +00:00
}
int CCharacter::NetworkClipped(int SnappingClient)
{
return NetworkClipped(SnappingClient, m_Pos);
}
int CCharacter::NetworkClipped(int SnappingClient, vec2 CheckPos)
{
2014-02-02 18:56:10 +00:00
if(SnappingClient == -1 || GameServer()->m_apPlayers[SnappingClient]->m_ShowAll)
return 0;
float dx = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.x-CheckPos.x;
float dy = GameServer()->m_apPlayers[SnappingClient]->m_ViewPos.y-CheckPos.y;
if(absolute(dx) > 1000.0f || absolute(dy) > 800.0f)
return 1;
if(distance(GameServer()->m_apPlayers[SnappingClient]->m_ViewPos, CheckPos) > 4000.0f)
return 1;
return 0;
}
// DDRace
bool CCharacter::CanCollide(int ClientID)
2011-01-29 00:59:50 +00:00
{
return Teams()->m_Core.CanCollide(GetPlayer()->GetCID(), ClientID);
2011-01-29 00:59:50 +00:00
}
bool CCharacter::SameTeam(int ClientID)
2011-01-29 00:59:50 +00:00
{
return Teams()->m_Core.SameTeam(GetPlayer()->GetCID(), ClientID);
2011-01-29 00:59:50 +00:00
}
int CCharacter::Team()
{
return Teams()->m_Core.Team(m_pPlayer->GetCID());
}
CGameTeams* CCharacter::Teams()
{
2011-01-29 00:59:50 +00:00
return &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams;
}
2011-06-05 11:56:04 +00:00
void CCharacter::FillAntibot(CAntibotCharacterData *pData)
{
pData->m_Pos = m_Pos;
pData->m_Vel = m_Core.m_Vel;
pData->m_Angle = m_Core.m_Angle;
pData->m_HookedPlayer = m_Core.m_HookedPlayer;
pData->m_SpawnTick = m_SpawnTick;
pData->m_WeaponChangeTick = m_WeaponChangeTick;
pData->m_aLatestInputs[0].m_TargetX = m_LatestInput.m_TargetX;
pData->m_aLatestInputs[0].m_TargetY = m_LatestInput.m_TargetY;
pData->m_aLatestInputs[1].m_TargetX = m_LatestPrevInput.m_TargetX;
pData->m_aLatestInputs[1].m_TargetY = m_LatestPrevInput.m_TargetY;
pData->m_aLatestInputs[2].m_TargetX = m_LatestPrevPrevInput.m_TargetX;
pData->m_aLatestInputs[2].m_TargetY = m_LatestPrevPrevInput.m_TargetY;
}
2011-01-29 00:59:50 +00:00
void CCharacter::HandleBroadcast()
{
2010-10-08 13:33:42 +00:00
CPlayerData *pData = GameServer()->Score()->PlayerData(m_pPlayer->GetCID());
2013-03-18 11:58:29 +00:00
if(m_DDRaceState == DDRACE_STARTED && m_CpLastBroadcast != m_CpActive &&
m_CpActive > -1 && m_CpTick > Server()->Tick() && m_pPlayer->GetClientVersion() == VERSION_VANILLA &&
2011-06-05 11:56:04 +00:00
pData->m_BestTime && pData->m_aBestCpTime[m_CpActive] != 0)
2010-10-08 13:33:42 +00:00
{
Added the following settings to Close #123. sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands" sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time" sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands" Added the following Chat commands to give the player the choice over their settings: "saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race" "saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race" "time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message" "broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status" "servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status" Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect. So now players have the choice to see which timer they wanna see if any. Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
char aBroadcast[128];
2011-06-05 11:56:04 +00:00
float Diff = m_CpCurrent[m_CpActive] - pData->m_aBestCpTime[m_CpActive];
str_format(aBroadcast, sizeof(aBroadcast), "Checkpoint | Diff : %+5.2f", Diff);
GameServer()->SendBroadcast(aBroadcast, m_pPlayer->GetCID());
2013-03-18 11:58:29 +00:00
m_CpLastBroadcast = m_CpActive;
2011-06-05 11:56:04 +00:00
m_LastBroadcast = Server()->Tick();
}
else if ((m_pPlayer->m_TimerType == CPlayer::TIMERTYPE_BROADCAST || m_pPlayer->m_TimerType == CPlayer::TIMERTYPE_GAMETIMER_AND_BROADCAST) && m_DDRaceState == DDRACE_STARTED && m_LastBroadcast + Server()->TickSpeed() * g_Config.m_SvTimeInBroadcastInterval <= Server()->Tick())
Added the following settings to Close #123. sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands" sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time" sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands" Added the following Chat commands to give the player the choice over their settings: "saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race" "saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race" "time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message" "broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status" "servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status" Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect. So now players have the choice to see which timer they wanna see if any. Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
{
char aBuftime[64];
int IntTime = (int)((float)(Server()->Tick() - m_StartTime) / ((float)Server()->TickSpeed()));
str_format(aBuftime, sizeof(aBuftime), "%s%d:%s%d", ((IntTime/60) > 9)?"":"0", IntTime/60, ((IntTime%60) > 9)?"":"0", IntTime%60);
2018-03-07 16:22:41 +00:00
GameServer()->SendBroadcast(aBuftime, m_pPlayer->GetCID(), false);
2013-03-18 11:58:29 +00:00
m_CpLastBroadcast = m_CpActive;
Added the following settings to Close #123. sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands" sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time" sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands" Added the following Chat commands to give the player the choice over their settings: "saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race" "saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race" "time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message" "broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status" "servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status" Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect. So now players have the choice to see which timer they wanna see if any. Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
m_LastBroadcast = Server()->Tick();
}
2011-01-29 00:59:50 +00:00
}
2011-01-29 00:59:50 +00:00
void CCharacter::HandleSkippableTiles(int Index)
{
// handle death-tiles and leaving gamelayer
2015-11-08 09:20:10 +00:00
if((GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f) == TILE_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f) == TILE_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f) == TILE_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f) == TILE_DEATH||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f) == TILE_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f) == TILE_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f) == TILE_DEATH) &&
2011-08-31 21:36:41 +00:00
!m_Super && !(Team() && Teams()->TeeFinished(m_pPlayer->GetCID())))
2014-01-31 22:24:45 +00:00
{
Die(m_pPlayer->GetCID(), WEAPON_WORLD);
return;
}
if (GameLayerClipped(m_Pos))
2014-01-31 22:24:45 +00:00
{
Die(m_pPlayer->GetCID(), WEAPON_WORLD);
return;
}
if(Index < 0)
return;
// handle speedup tiles
2011-01-29 00:59:50 +00:00
if(GameServer()->Collision()->IsSpeedup(Index))
{
vec2 Direction, MaxVel, TempVel = m_Core.m_Vel;
int Force, MaxSpeed = 0;
float TeeAngle, SpeederAngle, DiffAngle, SpeedLeft, TeeSpeed;
2011-01-29 00:59:50 +00:00
GameServer()->Collision()->GetSpeedup(Index, &Direction, &Force, &MaxSpeed);
if(Force == 255 && MaxSpeed)
{
m_Core.m_Vel = Direction * (MaxSpeed/5);
}
else
{
if(MaxSpeed > 0 && MaxSpeed < 5) MaxSpeed = 5;
if(MaxSpeed > 0)
{
if(Direction.x > 0.0000001f)
SpeederAngle = -atan(Direction.y / Direction.x);
else if(Direction.x < 0.0000001f)
SpeederAngle = atan(Direction.y / Direction.x) + 2.0f * asin(1.0f);
else if(Direction.y > 0.0000001f)
SpeederAngle = asin(1.0f);
else
SpeederAngle = asin(-1.0f);
if(SpeederAngle < 0)
SpeederAngle = 4.0f * asin(1.0f) + SpeederAngle;
if(TempVel.x > 0.0000001f)
TeeAngle = -atan(TempVel.y / TempVel.x);
else if(TempVel.x < 0.0000001f)
TeeAngle = atan(TempVel.y / TempVel.x) + 2.0f * asin(1.0f);
else if(TempVel.y > 0.0000001f)
TeeAngle = asin(1.0f);
else
TeeAngle = asin(-1.0f);
if(TeeAngle < 0)
TeeAngle = 4.0f * asin(1.0f) + TeeAngle;
TeeSpeed = sqrt(pow(TempVel.x, 2) + pow(TempVel.y, 2));
DiffAngle = SpeederAngle - TeeAngle;
SpeedLeft = MaxSpeed / 5.0f - cos(DiffAngle) * TeeSpeed;
2015-04-18 20:29:28 +00:00
if(abs((int)SpeedLeft) > Force && SpeedLeft > 0.0000001f)
TempVel += Direction * Force;
2015-04-18 20:29:28 +00:00
else if(abs((int)SpeedLeft) > Force)
TempVel += Direction * -Force;
else
TempVel += Direction * SpeedLeft;
}
else
TempVel += Direction * Force;
m_Core.m_Vel = ClampVel(m_MoveRestrictions, TempVel);
}
}
}
bool CCharacter::IsSwitchActiveCb(int Number, void *pUser)
{
CCharacter *pThis = (CCharacter *)pUser;
CCollision *pCollision = pThis->GameServer()->Collision();
return pCollision->m_pSwitchers && pCollision->m_pSwitchers[Number].m_Status[pThis->Team()] && pThis->Team() != TEAM_SUPER;
}
2010-10-08 13:33:42 +00:00
void CCharacter::HandleTiles(int Index)
2011-01-29 00:59:50 +00:00
{
2010-10-08 13:33:42 +00:00
CGameControllerDDRace* Controller = (CGameControllerDDRace*)GameServer()->m_pController;
int MapIndex = Index;
//int PureMapIndex = GameServer()->Collision()->GetPureMapIndex(m_Pos);
2010-10-08 13:33:42 +00:00
m_TileIndex = GameServer()->Collision()->GetTileIndex(MapIndex);
m_TileFIndex = GameServer()->Collision()->GetFTileIndex(MapIndex);
m_MoveRestrictions = GameServer()->Collision()->GetMoveRestrictions(IsSwitchActiveCb, this, m_Pos, 18.0f, MapIndex);
//Sensitivity
int S1 = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x + m_ProximityRadius / 3.f, m_Pos.y - m_ProximityRadius / 3.f));
int S2 = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x + m_ProximityRadius / 3.f, m_Pos.y + m_ProximityRadius / 3.f));
int S3 = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x - m_ProximityRadius / 3.f, m_Pos.y - m_ProximityRadius / 3.f));
int S4 = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x - m_ProximityRadius / 3.f, m_Pos.y + m_ProximityRadius / 3.f));
int Tile1 = GameServer()->Collision()->GetTileIndex(S1);
int Tile2 = GameServer()->Collision()->GetTileIndex(S2);
int Tile3 = GameServer()->Collision()->GetTileIndex(S3);
int Tile4 = GameServer()->Collision()->GetTileIndex(S4);
int FTile1 = GameServer()->Collision()->GetFTileIndex(S1);
int FTile2 = GameServer()->Collision()->GetFTileIndex(S2);
int FTile3 = GameServer()->Collision()->GetFTileIndex(S3);
int FTile4 = GameServer()->Collision()->GetFTileIndex(S4);
2011-02-01 12:01:05 +00:00
if(Index < 0)
2014-02-09 22:31:29 +00:00
{
m_LastRefillJumps = false;
2014-02-09 22:31:29 +00:00
m_LastPenalty = false;
m_LastBonus = false;
2011-02-01 12:01:05 +00:00
return;
2014-02-09 22:31:29 +00:00
}
2010-10-08 13:33:42 +00:00
int cp = GameServer()->Collision()->IsCheckpoint(MapIndex);
2010-10-29 21:28:15 +00:00
if(cp != -1 && m_DDRaceState == DDRACE_STARTED && cp > m_CpActive)
2010-10-08 13:33:42 +00:00
{
m_CpActive = cp;
m_CpCurrent[cp] = m_Time;
m_CpTick = Server()->Tick() + Server()->TickSpeed() * 2;
if(m_pPlayer->GetClientVersion() >= VERSION_DDRACE) {
2010-11-30 02:24:15 +00:00
CPlayerData *pData = GameServer()->Score()->PlayerData(m_pPlayer->GetCID());
CNetMsg_Sv_DDRaceTime Msg;
Msg.m_Time = (int)m_Time;
Msg.m_Check = 0;
Msg.m_Finish = 0;
if(m_CpActive != -1 && m_CpTick > Server()->Tick())
{
if(pData->m_BestTime && pData->m_aBestCpTime[m_CpActive] != 0)
{
float Diff = (m_CpCurrent[m_CpActive] - pData->m_aBestCpTime[m_CpActive])*100;
Msg.m_Check = (int)Diff;
}
}
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID());
}
2010-10-08 13:33:42 +00:00
}
2010-10-30 18:48:30 +00:00
int cpf = GameServer()->Collision()->IsFCheckpoint(MapIndex);
if(cpf != -1 && m_DDRaceState == DDRACE_STARTED && cpf > m_CpActive)
{
m_CpActive = cpf;
m_CpCurrent[cpf] = m_Time;
m_CpTick = Server()->Tick() + Server()->TickSpeed()*2;
if(m_pPlayer->GetClientVersion() >= VERSION_DDRACE) {
2010-11-30 02:24:15 +00:00
CPlayerData *pData = GameServer()->Score()->PlayerData(m_pPlayer->GetCID());
CNetMsg_Sv_DDRaceTime Msg;
Msg.m_Time = (int)m_Time;
Msg.m_Check = 0;
Msg.m_Finish = 0;
if(m_CpActive != -1 && m_CpTick > Server()->Tick())
{
if(pData->m_BestTime && pData->m_aBestCpTime[m_CpActive] != 0)
{
float Diff = (m_CpCurrent[m_CpActive] - pData->m_aBestCpTime[m_CpActive])*100;
Msg.m_Check = (int)Diff;
}
}
Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, m_pPlayer->GetCID());
}
2010-10-30 18:48:30 +00:00
}
int tcp = GameServer()->Collision()->IsTCheckpoint(MapIndex);
if(tcp)
m_TeleCheckpoint = tcp;
// start
if(((m_TileIndex == TILE_BEGIN) || (m_TileFIndex == TILE_BEGIN) || FTile1 == TILE_BEGIN || FTile2 == TILE_BEGIN || FTile3 == TILE_BEGIN || FTile4 == TILE_BEGIN || Tile1 == TILE_BEGIN || Tile2 == TILE_BEGIN || Tile3 == TILE_BEGIN || Tile4 == TILE_BEGIN) && (m_DDRaceState == DDRACE_NONE || m_DDRaceState == DDRACE_FINISHED || (m_DDRaceState == DDRACE_STARTED && !Team() && g_Config.m_SvTeam != 3)))
2010-10-08 13:33:42 +00:00
{
2014-09-23 15:33:33 +00:00
if(g_Config.m_SvResetPickups)
{
for (int i = WEAPON_SHOTGUN; i < NUM_WEAPONS; ++i)
{
m_aWeapons[i].m_Got = false;
2014-04-14 08:56:14 +00:00
if(m_Core.m_ActiveWeapon == i)
m_Core.m_ActiveWeapon = WEAPON_GUN;
}
}
2011-02-14 21:34:46 +00:00
if(g_Config.m_SvTeam == 2 && (Team() == TEAM_FLOCK || Teams()->Count(Team()) <= 1))
2011-01-29 14:31:50 +00:00
{
if(m_LastStartWarning < Server()->Tick() - 3 * Server()->TickSpeed())
{
2019-02-27 18:46:01 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You have to be in a team with other tees to start");
2011-01-29 14:31:50 +00:00
m_LastStartWarning = Server()->Tick();
}
2012-04-11 13:36:11 +00:00
Die(GetPlayer()->GetCID(), WEAPON_WORLD);
return;
2010-11-06 22:54:35 +00:00
}
Teams()->OnCharacterStart(m_pPlayer->GetCID());
m_CpActive = -2;
2010-10-08 13:33:42 +00:00
}
// finish
if(((m_TileIndex == TILE_END) || (m_TileFIndex == TILE_END) || FTile1 == TILE_END || FTile2 == TILE_END || FTile3 == TILE_END || FTile4 == TILE_END || Tile1 == TILE_END || Tile2 == TILE_END || Tile3 == TILE_END || Tile4 == TILE_END) && m_DDRaceState == DDRACE_STARTED)
2010-10-08 13:33:42 +00:00
Controller->m_Teams.OnCharacterFinish(m_pPlayer->GetCID());
// freeze
2011-01-14 13:37:02 +00:00
if(((m_TileIndex == TILE_FREEZE) || (m_TileFIndex == TILE_FREEZE)) && !m_Super && !m_DeepFreeze)
Freeze();
2011-01-14 13:37:02 +00:00
else if(((m_TileIndex == TILE_UNFREEZE) || (m_TileFIndex == TILE_UNFREEZE)) && !m_DeepFreeze)
2010-10-08 13:33:42 +00:00
UnFreeze();
// deep freeze
if(((m_TileIndex == TILE_DFREEZE) || (m_TileFIndex == TILE_DFREEZE)) && !m_Super && !m_DeepFreeze)
2011-01-14 13:37:02 +00:00
m_DeepFreeze = true;
else if(((m_TileIndex == TILE_DUNFREEZE) || (m_TileFIndex == TILE_DUNFREEZE)) && !m_Super && m_DeepFreeze)
m_DeepFreeze = false;
// endless hook
if(((m_TileIndex == TILE_EHOOK_START) || (m_TileFIndex == TILE_EHOOK_START)) && !m_EndlessHook)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Endless hook has been activated");
m_EndlessHook = true;
2019-04-21 13:16:28 +00:00
m_Core.m_EndlessHook = true;
}
else if(((m_TileIndex == TILE_EHOOK_END) || (m_TileFIndex == TILE_EHOOK_END)) && m_EndlessHook)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Endless hook has been deactivated");
m_EndlessHook = false;
2019-04-21 13:16:28 +00:00
m_Core.m_EndlessHook = false;
}
// hit others
if(((m_TileIndex == TILE_HIT_END) || (m_TileFIndex == TILE_HIT_END)) && m_Hit != (DISABLE_HIT_GRENADE|DISABLE_HIT_HAMMER|DISABLE_HIT_LASER|DISABLE_HIT_SHOTGUN))
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hit others");
m_Hit = DISABLE_HIT_GRENADE|DISABLE_HIT_HAMMER|DISABLE_HIT_LASER|DISABLE_HIT_SHOTGUN;
2019-04-21 13:16:28 +00:00
m_Core.m_NoShotgunHit = true;
m_Core.m_NoGrenadeHit = true;
m_Core.m_NoHammerHit = true;
m_Core.m_NoLaserHit = true;
2016-04-20 09:59:14 +00:00
m_NeededFaketuning |= FAKETUNE_NOHAMMER;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
else if(((m_TileIndex == TILE_HIT_START) || (m_TileFIndex == TILE_HIT_START)) && m_Hit != HIT_ALL)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can hit others");
m_Hit = HIT_ALL;
2019-04-21 13:16:28 +00:00
m_Core.m_NoShotgunHit = false;
m_Core.m_NoGrenadeHit = false;
m_Core.m_NoHammerHit = false;
m_Core.m_NoLaserHit = false;
2016-04-20 09:59:14 +00:00
m_NeededFaketuning &= ~FAKETUNE_NOHAMMER;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
// collide with others
if(((m_TileIndex == TILE_NPC_END) || (m_TileFIndex == TILE_NPC_END)) && m_Core.m_Collision)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't collide with others");
m_Core.m_Collision = false;
2019-04-21 13:16:28 +00:00
m_Core.m_NoCollision = true;
m_NeededFaketuning |= FAKETUNE_NOCOLL;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
else if(((m_TileIndex == TILE_NPC_START) || (m_TileFIndex == TILE_NPC_START)) && !m_Core.m_Collision)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can collide with others");
m_Core.m_Collision = true;
2019-04-21 13:16:28 +00:00
m_Core.m_NoCollision = false;
m_NeededFaketuning &= ~FAKETUNE_NOCOLL;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
// hook others
if(((m_TileIndex == TILE_NPH_END) || (m_TileFIndex == TILE_NPH_END)) && m_Core.m_Hook)
2013-11-22 14:10:55 +00:00
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hook others");
m_Core.m_Hook = false;
2019-04-21 13:16:28 +00:00
m_Core.m_NoHookHit = true;
m_NeededFaketuning |= FAKETUNE_NOHOOK;
2014-04-13 23:34:50 +00:00
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
2013-11-22 14:10:55 +00:00
}
else if(((m_TileIndex == TILE_NPH_START) || (m_TileFIndex == TILE_NPH_START)) && !m_Core.m_Hook)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can hook others");
m_Core.m_Hook = true;
2019-04-21 13:16:28 +00:00
m_Core.m_NoHookHit = false;
m_NeededFaketuning &= ~FAKETUNE_NOHOOK;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
// unlimited air jumps
if(((m_TileIndex == TILE_SUPER_START) || (m_TileFIndex == TILE_SUPER_START)) && !m_SuperJump)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You have unlimited air jumps");
m_SuperJump = true;
2019-04-21 13:16:28 +00:00
m_Core.m_EndlessJump = true;
if (m_Core.m_Jumps == 0)
{
m_NeededFaketuning &= ~FAKETUNE_NOJUMP;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
}
else if(((m_TileIndex == TILE_SUPER_END) || (m_TileFIndex == TILE_SUPER_END)) && m_SuperJump)
{
2014-09-27 17:10:15 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You don't have unlimited air jumps");
m_SuperJump = false;
2019-04-21 13:16:28 +00:00
m_Core.m_EndlessJump = false;
2014-03-01 13:29:14 +00:00
if (m_Core.m_Jumps == 0)
{
m_NeededFaketuning |= FAKETUNE_NOJUMP;
2014-03-24 20:03:55 +00:00
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
2014-03-01 13:29:14 +00:00
}
}
// walljump
if((m_TileIndex == TILE_WALLJUMP) || (m_TileFIndex == TILE_WALLJUMP))
2014-06-21 22:50:11 +00:00
{
if(m_Core.m_Vel.y > 0 && m_Core.m_Colliding && m_Core.m_LeftWall)
2014-06-21 22:50:11 +00:00
{
2014-06-23 12:46:27 +00:00
m_Core.m_LeftWall = false;
m_Core.m_JumpedTotal = m_Core.m_Jumps - 1;
2014-06-21 22:50:11 +00:00
m_Core.m_Jumped = 1;
}
}
// jetpack gun
if(((m_TileIndex == TILE_JETPACK_START) || (m_TileFIndex == TILE_JETPACK_START)) && !m_Jetpack)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You have a jetpack gun");
m_Jetpack = true;
2019-04-21 13:16:28 +00:00
m_Core.m_Jetpack = true;
}
2013-11-22 14:10:55 +00:00
else if(((m_TileIndex == TILE_JETPACK_END) || (m_TileFIndex == TILE_JETPACK_END)) && m_Jetpack)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You lost your jetpack gun");
m_Jetpack = false;
2019-04-21 13:16:28 +00:00
m_Core.m_Jetpack = false;
2013-11-22 14:10:55 +00:00
}
// unlock team
else if(((m_TileIndex == TILE_UNLOCK_TEAM) || (m_TileFIndex == TILE_UNLOCK_TEAM)) && Teams()->TeamLocked(Team()))
{
Teams()->SetTeamLock(Team(), false);
for(int i = 0; i < MAX_CLIENTS; i++)
if(Teams()->m_Core.Team(i) == Team())
2016-07-03 21:23:33 +00:00
GameServer()->SendChatTarget(i, "Your team was unlocked by an unlock team tile");
}
// solo part
if(((m_TileIndex == TILE_SOLO_START) || (m_TileFIndex == TILE_SOLO_START)) && !Teams()->m_Core.GetSolo(m_pPlayer->GetCID()))
{
2016-07-03 21:23:33 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You are now in a solo part");
SetSolo(true);
}
else if(((m_TileIndex == TILE_SOLO_END) || (m_TileFIndex == TILE_SOLO_END)) && Teams()->m_Core.GetSolo(m_pPlayer->GetCID()))
{
2016-07-03 21:23:33 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You are now out of the solo part");
SetSolo(false);
}
// refill jumps
if(((m_TileIndex == TILE_REFILL_JUMPS) || (m_TileFIndex == TILE_REFILL_JUMPS)) && !m_LastRefillJumps)
{
m_Core.m_JumpedTotal = 0;
2015-03-22 17:27:57 +00:00
m_Core.m_Jumped = 0;
m_LastRefillJumps = true;
}
if((m_TileIndex != TILE_REFILL_JUMPS) && (m_TileFIndex != TILE_REFILL_JUMPS))
{
m_LastRefillJumps = false;
}
2018-02-14 15:27:26 +00:00
// Teleport gun
2019-08-19 08:09:53 +00:00
if (((m_TileIndex == TILE_TELE_GUN_ENABLE) || (m_TileFIndex == TILE_TELE_GUN_ENABLE)) && !m_Core.m_HasTelegunGun)
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core.m_HasTelegunGun = true;
2018-02-14 15:27:26 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport gun enabled");
}
2019-08-19 08:09:53 +00:00
else if (((m_TileIndex == TILE_TELE_GUN_DISABLE) || (m_TileFIndex == TILE_TELE_GUN_DISABLE)) && m_Core.m_HasTelegunGun)
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core.m_HasTelegunGun = false;
2018-02-14 15:27:26 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport gun disabled");
}
2019-08-19 08:09:53 +00:00
if (((m_TileIndex == TILE_TELE_GRENADE_ENABLE) || (m_TileFIndex == TILE_TELE_GRENADE_ENABLE)) && !m_Core.m_HasTelegunGrenade)
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core.m_HasTelegunGrenade = true;
2018-02-14 15:27:26 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport grenade enabled");
}
2019-08-19 08:09:53 +00:00
else if (((m_TileIndex == TILE_TELE_GRENADE_DISABLE) || (m_TileFIndex == TILE_TELE_GRENADE_DISABLE)) && m_Core.m_HasTelegunGrenade)
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core.m_HasTelegunGrenade = false;
2018-02-14 15:27:26 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport grenade disabled");
}
2019-08-19 08:09:53 +00:00
if (((m_TileIndex == TILE_TELE_LASER_ENABLE) || (m_TileFIndex == TILE_TELE_LASER_ENABLE)) && !m_Core.m_HasTelegunLaser)
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core.m_HasTelegunLaser = true;
2018-02-14 15:27:26 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport laser enabled");
}
2019-08-19 08:09:53 +00:00
else if (((m_TileIndex == TILE_TELE_LASER_DISABLE) || (m_TileFIndex == TILE_TELE_LASER_DISABLE)) && m_Core.m_HasTelegunLaser)
2018-02-14 15:27:26 +00:00
{
2019-04-21 13:16:28 +00:00
m_Core.m_HasTelegunLaser = false;
2018-02-14 15:27:26 +00:00
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Teleport laser disabled");
}
// stopper
2019-10-15 08:38:34 +00:00
if(m_Core.m_Vel.y > 0 && (m_MoveRestrictions&CANTMOVE_DOWN))
2010-10-08 13:33:42 +00:00
{
m_Core.m_Jumped = 0;
m_Core.m_JumpedTotal = 0;
2010-10-08 13:33:42 +00:00
}
m_Core.m_Vel = ClampVel(m_MoveRestrictions, m_Core.m_Vel);
// handle switch tiles
if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_SWITCHOPEN && Team() != TEAM_SUPER && GameServer()->Collision()->GetSwitchNumber(MapIndex) > 0)
2010-11-22 20:43:22 +00:00
{
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()] = true;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_EndTick[Team()] = 0;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Type[Team()] = TILE_SWITCHOPEN;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_SWITCHTIMEDOPEN && Team() != TEAM_SUPER && GameServer()->Collision()->GetSwitchNumber(MapIndex) > 0)
2010-11-22 20:43:22 +00:00
{
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()] = true;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_EndTick[Team()] = Server()->Tick() + 1 + GameServer()->Collision()->GetSwitchDelay(MapIndex)*Server()->TickSpeed() ;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Type[Team()] = TILE_SWITCHTIMEDOPEN;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_SWITCHTIMEDCLOSE && Team() != TEAM_SUPER && GameServer()->Collision()->GetSwitchNumber(MapIndex) > 0)
2010-11-22 20:43:22 +00:00
{
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()] = false;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_EndTick[Team()] = Server()->Tick() + 1 + GameServer()->Collision()->GetSwitchDelay(MapIndex)*Server()->TickSpeed();
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Type[Team()] = TILE_SWITCHTIMEDCLOSE;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_SWITCHCLOSE && Team() != TEAM_SUPER && GameServer()->Collision()->GetSwitchNumber(MapIndex) > 0)
2010-11-22 20:43:22 +00:00
{
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()] = false;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_EndTick[Team()] = 0;
GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Type[Team()] = TILE_SWITCHCLOSE;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_FREEZE && Team() != TEAM_SUPER)
{
if(GameServer()->Collision()->GetSwitchNumber(MapIndex) == 0 || GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
Freeze(GameServer()->Collision()->GetSwitchDelay(MapIndex));
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER)
{
if(GameServer()->Collision()->GetSwitchNumber(MapIndex) == 0 || GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
m_DeepFreeze = true;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_DUNFREEZE && Team() != TEAM_SUPER)
{
if(GameServer()->Collision()->GetSwitchNumber(MapIndex) == 0 || GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetSwitchNumber(MapIndex)].m_Status[Team()])
m_DeepFreeze = false;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_START && m_Hit&DISABLE_HIT_HAMMER && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can hammer hit others");
m_Hit &= ~DISABLE_HIT_HAMMER;
2016-04-20 09:59:14 +00:00
m_NeededFaketuning &= ~FAKETUNE_NOHAMMER;
2019-04-21 13:16:28 +00:00
m_Core.m_NoHammerHit = false;
2016-04-20 09:59:14 +00:00
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_END && !(m_Hit&DISABLE_HIT_HAMMER) && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_HAMMER)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can't hammer hit others");
m_Hit |= DISABLE_HIT_HAMMER;
2016-04-20 09:59:14 +00:00
m_NeededFaketuning |= FAKETUNE_NOHAMMER;
2019-04-21 13:16:28 +00:00
m_Core.m_NoHammerHit = true;
2016-04-20 09:59:14 +00:00
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_START && m_Hit&DISABLE_HIT_SHOTGUN && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can shoot others with shotgun");
m_Hit &= ~DISABLE_HIT_SHOTGUN;
2019-04-21 13:16:28 +00:00
m_Core.m_NoShotgunHit = false;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_END && !(m_Hit&DISABLE_HIT_SHOTGUN) && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_SHOTGUN)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can't shoot others with shotgun");
m_Hit |= DISABLE_HIT_SHOTGUN;
2019-04-21 13:16:28 +00:00
m_Core.m_NoShotgunHit = true;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_START && m_Hit&DISABLE_HIT_GRENADE && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can shoot others with grenade");
m_Hit &= ~DISABLE_HIT_GRENADE;
2019-04-21 13:16:28 +00:00
m_Core.m_NoGrenadeHit = false;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_END && !(m_Hit&DISABLE_HIT_GRENADE) && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_GRENADE)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can't shoot others with grenade");
m_Hit |= DISABLE_HIT_GRENADE;
2019-04-21 13:16:28 +00:00
m_Core.m_NoGrenadeHit = true;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_START && m_Hit&DISABLE_HIT_LASER && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can shoot others with laser");
m_Hit &= ~DISABLE_HIT_LASER;
m_Core.m_NoLaserHit = false;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_END && !(m_Hit&DISABLE_HIT_LASER) && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_LASER)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can't shoot others with laser");
m_Hit |= DISABLE_HIT_LASER;
m_Core.m_NoLaserHit = true;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_JUMP)
{
int newJumps = GameServer()->Collision()->GetSwitchDelay(MapIndex);
if (newJumps != m_Core.m_Jumps)
{
char aBuf[256];
2014-06-24 21:32:29 +00:00
if(newJumps == 1)
str_format(aBuf, sizeof(aBuf), "You can jump %d time", newJumps);
else
str_format(aBuf, sizeof(aBuf), "You can jump %d times", newJumps);
GameServer()->SendChatTarget(GetPlayer()->GetCID(),aBuf);
2014-03-01 13:29:14 +00:00
if (newJumps == 0 && !m_SuperJump)
{
2014-03-01 13:29:14 +00:00
m_NeededFaketuning |= FAKETUNE_NOJUMP;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
else if (m_Core.m_Jumps == 0)
{
m_NeededFaketuning &= ~FAKETUNE_NOJUMP;
GameServer()->SendTuningParams(m_pPlayer->GetCID(), m_TuneZone); // update tunings
}
m_Core.m_Jumps = newJumps;
}
}
2014-02-09 22:31:29 +00:00
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_PENALTY && !m_LastPenalty)
{
int min = GameServer()->Collision()->GetSwitchDelay(MapIndex);
int sec = GameServer()->Collision()->GetSwitchNumber(MapIndex);
2014-02-09 23:17:00 +00:00
int Team = Teams()->m_Core.Team(m_Core.m_Id);
2014-02-09 22:31:29 +00:00
m_StartTime -= (min * 60 + sec) * Server()->TickSpeed();
2014-02-09 23:17:00 +00:00
if (Team != TEAM_FLOCK && Team != TEAM_SUPER)
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
if(Teams()->m_Core.Team(i) == Team && i != m_Core.m_Id && GameServer()->m_apPlayers[i])
2014-02-09 23:17:00 +00:00
{
CCharacter* pChar = GameServer()->m_apPlayers[i]->GetCharacter();
if (pChar)
pChar->m_StartTime = m_StartTime;
}
}
}
2014-02-09 22:31:29 +00:00
m_LastPenalty = true;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_BONUS && !m_LastBonus)
{
int min = GameServer()->Collision()->GetSwitchDelay(MapIndex);
int sec = GameServer()->Collision()->GetSwitchNumber(MapIndex);
int Team = Teams()->m_Core.Team(m_Core.m_Id);
m_StartTime += (min * 60 + sec) * Server()->TickSpeed();
if (m_StartTime > Server()->Tick())
m_StartTime = Server()->Tick();
if (Team != TEAM_FLOCK && Team != TEAM_SUPER)
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
if(Teams()->m_Core.Team(i) == Team && i != m_Core.m_Id && GameServer()->m_apPlayers[i])
{
CCharacter* pChar = GameServer()->m_apPlayers[i]->GetCharacter();
if (pChar)
pChar->m_StartTime = m_StartTime;
}
}
}
m_LastBonus = true;
}
2014-02-09 22:31:29 +00:00
if(GameServer()->Collision()->IsSwitch(MapIndex) != TILE_PENALTY)
{
m_LastPenalty = false;
}
if(GameServer()->Collision()->IsSwitch(MapIndex) != TILE_BONUS)
{
m_LastBonus = false;
}
2010-10-08 13:33:42 +00:00
int z = GameServer()->Collision()->IsTeleport(MapIndex);
2013-08-13 02:59:25 +00:00
if(!g_Config.m_SvOldTeleportHook && !g_Config.m_SvOldTeleportWeapons && z && Controller->m_TeleOuts[z-1].size())
2010-10-08 13:33:42 +00:00
{
2014-01-13 16:00:49 +00:00
if (m_Super)
return;
2020-05-25 13:08:24 +00:00
int TeleOut = m_Core.m_pWorld->RandomOr0(Controller->m_TeleOuts[z-1].size());
m_Core.m_Pos = Controller->m_TeleOuts[z-1][TeleOut];
2014-04-04 22:35:18 +00:00
if(!g_Config.m_SvTeleportHoldHook)
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_Core.m_HookPos = m_Core.m_Pos;
}
2015-08-22 17:24:10 +00:00
if(g_Config.m_SvTeleportLoseWeapons)
{
2015-08-22 18:25:28 +00:00
for(int i=WEAPON_SHOTGUN;i<NUM_WEAPONS-1;i++)
2015-08-22 17:24:10 +00:00
m_aWeapons[i].m_Got = false;
}
2010-10-10 23:46:13 +00:00
return;
2010-10-08 13:33:42 +00:00
}
int evilz = GameServer()->Collision()->IsEvilTeleport(MapIndex);
2014-01-13 16:00:49 +00:00
if(evilz && Controller->m_TeleOuts[evilz-1].size())
2010-10-08 13:33:42 +00:00
{
2014-01-13 16:00:49 +00:00
if (m_Super)
return;
2020-05-25 13:08:24 +00:00
int TeleOut = m_Core.m_pWorld->RandomOr0(Controller->m_TeleOuts[evilz-1].size());
m_Core.m_Pos = Controller->m_TeleOuts[evilz-1][TeleOut];
2013-08-13 02:59:25 +00:00
if (!g_Config.m_SvOldTeleportHook && !g_Config.m_SvOldTeleportWeapons)
{
m_Core.m_Vel = vec2(0,0);
2014-04-04 22:35:18 +00:00
if(!g_Config.m_SvTeleportHoldHook)
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
GameWorld()->ReleaseHooked(GetPlayer()->GetCID());
m_Core.m_HookPos = m_Core.m_Pos;
}
2015-08-22 17:24:10 +00:00
if(g_Config.m_SvTeleportLoseWeapons)
{
2015-08-22 18:15:15 +00:00
for(int i=WEAPON_SHOTGUN;i<NUM_WEAPONS-1;i++)
2015-08-22 17:24:10 +00:00
m_aWeapons[i].m_Got = false;
}
}
2010-10-10 23:46:13 +00:00
return;
2010-10-08 13:33:42 +00:00
}
2014-02-01 21:20:41 +00:00
if(GameServer()->Collision()->IsCheckEvilTeleport(MapIndex))
{
if (m_Super)
return;
// first check if there is a TeleCheckOut for the current recorded checkpoint, if not check previous checkpoints
for(int k=m_TeleCheckpoint-1; k >= 0; k--)
{
if(Controller->m_TeleCheckOuts[k].size())
{
2020-05-25 13:08:24 +00:00
int TeleOut = m_Core.m_pWorld->RandomOr0(Controller->m_TeleCheckOuts[k].size());
m_Core.m_Pos = Controller->m_TeleCheckOuts[k][TeleOut];
2014-02-01 21:20:41 +00:00
m_Core.m_Vel = vec2(0,0);
if(!g_Config.m_SvTeleportHoldHook)
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
GameWorld()->ReleaseHooked(GetPlayer()->GetCID());
m_Core.m_HookPos = m_Core.m_Pos;
}
2014-02-01 21:20:41 +00:00
return;
}
}
// if no checkpointout have been found (or if there no recorded checkpoint), teleport to start
vec2 SpawnPos;
if(GameServer()->m_pController->CanSpawn(m_pPlayer->GetTeam(), &SpawnPos))
{
m_Core.m_Pos = SpawnPos;
m_Core.m_Vel = vec2(0,0);
if(!g_Config.m_SvTeleportHoldHook)
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
GameWorld()->ReleaseHooked(GetPlayer()->GetCID());
m_Core.m_HookPos = m_Core.m_Pos;
}
2014-02-01 21:20:41 +00:00
}
return;
}
if(GameServer()->Collision()->IsCheckTeleport(MapIndex))
{
2014-01-13 16:00:49 +00:00
if (m_Super)
return;
// first check if there is a TeleCheckOut for the current recorded checkpoint, if not check previous checkpoints
for(int k=m_TeleCheckpoint-1; k >= 0; k--)
{
if(Controller->m_TeleCheckOuts[k].size())
{
2020-05-25 13:08:24 +00:00
int TeleOut = m_Core.m_pWorld->RandomOr0(Controller->m_TeleCheckOuts[k].size());
m_Core.m_Pos = Controller->m_TeleCheckOuts[k][TeleOut];
if(!g_Config.m_SvTeleportHoldHook)
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_Core.m_HookPos = m_Core.m_Pos;
}
return;
}
}
// if no checkpointout have been found (or if there no recorded checkpoint), teleport to start
vec2 SpawnPos;
if(GameServer()->m_pController->CanSpawn(m_pPlayer->GetTeam(), &SpawnPos))
{
m_Core.m_Pos = SpawnPos;
if(!g_Config.m_SvTeleportHoldHook)
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_Core.m_HookPos = m_Core.m_Pos;
}
}
return;
}
2010-10-08 13:33:42 +00:00
}
void CCharacter::HandleTuneLayer()
{
2015-07-09 00:08:14 +00:00
2014-04-13 14:49:58 +00:00
m_TuneZoneOld = m_TuneZone;
int CurrentIndex = GameServer()->Collision()->GetMapIndex(m_Pos);
m_TuneZone = GameServer()->Collision()->IsTune(CurrentIndex);
2014-04-13 14:49:58 +00:00
if(m_TuneZone)
m_Core.m_pWorld->m_Tuning[g_Config.m_ClDummy] = GameServer()->TuningList()[m_TuneZone]; // throw tunings from specific zone into gamecore
else
m_Core.m_pWorld->m_Tuning[g_Config.m_ClDummy] = *GameServer()->Tuning();
2014-04-13 14:49:58 +00:00
2018-02-04 15:00:47 +00:00
if (m_TuneZone != m_TuneZoneOld) // don't send tunigs all the time
{
2014-04-18 12:27:58 +00:00
// send zone msgs
SendZoneMsgs();
}
}
2014-04-13 23:34:50 +00:00
2014-04-18 12:27:58 +00:00
void CCharacter::SendZoneMsgs()
{
// send zone leave msg
// (m_TuneZoneOld >= 0: avoid zone leave msgs on spawn)
if (m_TuneZoneOld >= 0 && GameServer()->m_aaZoneLeaveMsg[m_TuneZoneOld])
2014-04-18 12:27:58 +00:00
{
const char *pCur = GameServer()->m_aaZoneLeaveMsg[m_TuneZoneOld];
const char *pPos;
while ((pPos = str_find(pCur, "\\n")))
2014-04-13 17:27:08 +00:00
{
2014-04-18 12:27:58 +00:00
char aBuf[256];
str_copy(aBuf, pCur, pPos - pCur + 1);
aBuf[pPos - pCur + 1] = '\0';
pCur = pPos + 2;
2014-04-18 12:27:58 +00:00
GameServer()->SendChatTarget(m_pPlayer->GetCID(), aBuf);
2014-04-13 17:27:08 +00:00
}
GameServer()->SendChatTarget(m_pPlayer->GetCID(), pCur);
2014-04-18 12:27:58 +00:00
}
// send zone enter msg
if (GameServer()->m_aaZoneEnterMsg[m_TuneZone])
2014-04-18 12:27:58 +00:00
{
const char* pCur = GameServer()->m_aaZoneEnterMsg[m_TuneZone];
const char* pPos;
while ((pPos = str_find(pCur, "\\n")))
2014-04-13 17:27:08 +00:00
{
2014-04-18 12:27:58 +00:00
char aBuf[256];
str_copy(aBuf, pCur, pPos - pCur + 1);
aBuf[pPos - pCur + 1] = '\0';
pCur = pPos + 2;
2014-04-18 12:27:58 +00:00
GameServer()->SendChatTarget(m_pPlayer->GetCID(), aBuf);
2014-04-13 17:27:08 +00:00
}
GameServer()->SendChatTarget(m_pPlayer->GetCID(), pCur);
}
}
IAntibot *CCharacter::Antibot()
{
return GameServer()->Antibot();
}
2011-01-29 00:59:50 +00:00
void CCharacter::DDRaceTick()
{
2016-08-27 15:06:52 +00:00
mem_copy(&m_Input, &m_SavedInput, sizeof(m_Input));
2011-01-29 00:59:50 +00:00
m_Armor=(m_FreezeTime >= 0)?10-(m_FreezeTime/15):0;
if(m_Input.m_Direction != 0 || m_Input.m_Jump != 0)
m_LastMove = Server()->Tick();
2011-01-29 00:59:50 +00:00
if(m_FreezeTime > 0 || m_FreezeTime == -1)
2010-05-29 07:25:38 +00:00
{
if (m_FreezeTime % Server()->TickSpeed() == Server()->TickSpeed() - 1 || m_FreezeTime == -1)
{
GameServer()->CreateDamageInd(m_Pos, 0, (m_FreezeTime + 1) / Server()->TickSpeed(), Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
2011-01-29 00:59:50 +00:00
}
if(m_FreezeTime > 0)
m_FreezeTime--;
else
m_Ninja.m_ActivationTick = Server()->Tick();
m_Input.m_Direction = 0;
m_Input.m_Jump = 0;
m_Input.m_Hook = 0;
if (m_FreezeTime == 1)
UnFreeze();
2008-09-23 07:43:41 +00:00
}
2015-07-09 00:08:14 +00:00
HandleTuneLayer(); // need this before coretick
// look for save position for rescue feature
if(g_Config.m_SvRescue || (Team() > TEAM_FLOCK && Team() < TEAM_SUPER)) {
int index = GameServer()->Collision()->GetPureMapIndex(m_Pos);
int tile = GameServer()->Collision()->GetTileIndex(index);
int ftile = GameServer()->Collision()->GetFTileIndex(index);
if(IsGrounded() && tile != TILE_FREEZE && tile != TILE_DFREEZE && ftile != TILE_FREEZE && ftile != TILE_DFREEZE) {
m_PrevSavePos = m_Pos;
for(int i = 0; i< NUM_WEAPONS; i++)
{
m_aPrevSaveWeapons[i].m_AmmoRegenStart = m_aWeapons[i].m_AmmoRegenStart;
m_aPrevSaveWeapons[i].m_Ammo = m_aWeapons[i].m_Ammo;
m_aPrevSaveWeapons[i].m_Ammocost = m_aWeapons[i].m_Ammocost;
m_aPrevSaveWeapons[i].m_Got = m_aWeapons[i].m_Got;
}
m_SetSavePos = true;
}
}
2011-01-29 00:59:50 +00:00
m_Core.m_Id = GetPlayer()->GetCID();
}
void CCharacter::DDRacePostCoreTick()
{
2013-03-18 11:58:29 +00:00
m_Time = (float)(Server()->Tick() - m_StartTime) / ((float)Server()->TickSpeed());
Added the following settings to Close #123. sv_time_in_broadcast, 1, 0, 1, CFGFLAG_SERVER, "Whether to display time in broadcast every interval or not by default, later the choice can be changed by players via chat commands" sv_time_in_broadcast_interval, 1, 0, 60, CFGFLAG_SERVER, "How often to update the broadcast time" sv_time_in_gametimer, 0, 0, 1, CFGFLAG_SERVER, "Whether to display time in the round/game timer or not by default, later the choice can be changed by players via chat commands" Added the following Chat commands to give the player the choice over their settings: "saytime", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTime, this, "Privately messages you your current time in this current running race" "saytimeall", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSayTimeAll, this, "Publicly messages everyone your current time in this current running race" "time", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConTime, this, "Privately shows you your current time in this current running race in the broadcast message" "broadcasttime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetBroadcastTime, this, "Personal Setting of showing time in the broadcast, broadcasttime s, where s = on for on, off for off, toggle for toggle and nothing to show current status" "servergametime", "?s", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSetServerGameTime, this, "Personal Setting of showing time in the round/game timer, servergametime s, where s = on for on off for off, toggle for toggle and nothing to show current status" Fixed Chat Command "eyeemote" and made it a set + toggle instead of just toggle for better bin techneques Moved some vars from CCharacter to CPlayer to keep their status evern after death but not after disconnect. So now players have the choice to see which timer they wanna see if any. Note: These changes are all untested Stay away from this update on your main server until they are tested, i don't even know if they will compile propperly
2011-12-29 12:17:34 +00:00
if (m_pPlayer->m_DefEmoteReset >= 0 && m_pPlayer->m_DefEmoteReset <= Server()->Tick())
2014-06-21 22:50:11 +00:00
{
m_pPlayer->m_DefEmoteReset = -1;
2014-06-21 22:50:11 +00:00
m_EmoteType = m_pPlayer->m_DefEmote = EMOTE_NORMAL;
m_EmoteStop = -1;
}
2014-06-21 22:50:11 +00:00
if (m_EndlessHook || (m_Super && g_Config.m_SvEndlessSuperHook))
m_Core.m_HookTick = 0;
m_FrozenLastTick = false;
2014-06-21 22:50:11 +00:00
if (m_DeepFreeze && !m_Super)
Freeze();
2014-06-21 22:50:11 +00:00
if (m_Core.m_Jumps == 0 && !m_Super)
m_Core.m_Jumped = 3;
else if (m_Core.m_Jumps == 1 && m_Core.m_Jumped > 0)
m_Core.m_Jumped = 3;
else if (m_Core.m_JumpedTotal < m_Core.m_Jumps - 1 && m_Core.m_Jumped > 1)
m_Core.m_Jumped = 1;
2013-08-24 00:25:58 +00:00
2014-06-21 22:50:11 +00:00
if ((m_Super || m_SuperJump) && m_Core.m_Jumped > 1)
m_Core.m_Jumped = 1;
2014-06-21 22:50:11 +00:00
int CurrentIndex = GameServer()->Collision()->GetMapIndex(m_Pos);
HandleSkippableTiles(CurrentIndex);
if(!m_Alive)
return;
2014-06-21 22:50:11 +00:00
// handle Anti-Skip tiles
std::list < int > Indices = GameServer()->Collision()->GetMapIndices(m_PrevPos, m_Pos);
if(!Indices.empty())
{
2014-06-21 22:50:11 +00:00
for(std::list < int >::iterator i = Indices.begin(); i != Indices.end(); i++)
{
2014-06-21 22:50:11 +00:00
HandleTiles(*i);
if(!m_Alive)
return;
}
}
2014-06-21 22:50:11 +00:00
else
{
HandleTiles(CurrentIndex);
if(!m_Alive)
return;
2014-06-21 22:50:11 +00:00
}
2018-07-15 09:58:12 +00:00
// teleport gun
if (m_TeleGunTeleport)
{
GameServer()->CreateDeath(m_Pos, m_pPlayer->GetCID(), Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
m_Core.m_Pos = m_TeleGunPos;
2018-11-02 23:02:20 +00:00
if(!m_IsBlueTeleGunTeleport)
m_Core.m_Vel = vec2(0, 0);
2018-07-15 09:58:12 +00:00
GameServer()->CreateDeath(m_TeleGunPos, m_pPlayer->GetCID(), Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
GameServer()->CreateSound(m_TeleGunPos, SOUND_WEAPON_SPAWN, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
m_TeleGunTeleport = false;
2018-11-02 23:02:20 +00:00
m_IsBlueTeleGunTeleport = false;
2018-07-15 09:58:12 +00:00
}
2014-06-21 22:50:11 +00:00
HandleBroadcast();
}
bool CCharacter::Freeze(int Seconds)
{
if ((Seconds <= 0 || m_Super || m_FreezeTime == -1 || m_FreezeTime > Seconds * Server()->TickSpeed()) && Seconds != -1)
return false;
if (m_FreezeTick < Server()->Tick() - Server()->TickSpeed() || Seconds == -1)
{
m_Armor = 0;
m_FreezeTime = Seconds == -1 ? Seconds : Seconds * Server()->TickSpeed();
m_FreezeTick = Server()->Tick();
return true;
}
return false;
}
bool CCharacter::Freeze()
{
return Freeze(g_Config.m_SvFreezeDelay);
}
bool CCharacter::UnFreeze()
{
if (m_FreezeTime > 0)
{
m_Armor=10;
2014-04-14 08:56:14 +00:00
if(!m_aWeapons[m_Core.m_ActiveWeapon].m_Got)
m_Core.m_ActiveWeapon = WEAPON_GUN;
m_FreezeTime = 0;
m_FreezeTick = 0;
m_FrozenLastTick = true;
return true;
}
return false;
}
2016-10-08 17:42:42 +00:00
void CCharacter::GiveWeapon(int Weapon, bool Remove)
{
if (Weapon == WEAPON_NINJA)
{
if (Remove)
RemoveNinja();
else
GiveNinja();
return;
}
2017-02-21 16:10:08 +00:00
2016-10-08 17:42:42 +00:00
if (Remove)
{
if (GetActiveWeapon()== Weapon)
SetActiveWeapon(WEAPON_GUN);
}
else
{
2020-03-16 10:52:53 +00:00
m_aWeapons[Weapon].m_Ammo = -1;
2016-10-08 17:42:42 +00:00
}
m_aWeapons[Weapon].m_Got = !Remove;
}
void CCharacter::GiveAllWeapons()
{
2015-08-22 18:15:15 +00:00
for(int i=WEAPON_GUN;i<NUM_WEAPONS-1;i++)
2014-12-15 19:48:58 +00:00
{
2016-10-08 17:42:42 +00:00
GiveWeapon(i);
2014-12-15 19:48:58 +00:00
}
}
void CCharacter::Pause(bool Pause)
{
m_Paused = Pause;
if(Pause)
{
GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
GameServer()->m_World.RemoveEntity(this);
2014-12-15 19:49:16 +00:00
if (m_Core.m_HookedPlayer != -1) // Keeping hook would allow cheats
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
}
}
else
{
m_Core.m_Vel = vec2(0,0);
GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = &m_Core;
GameServer()->m_World.InsertEntity(this);
}
}
2011-01-29 00:59:50 +00:00
void CCharacter::DDRaceInit()
{
m_Paused = false;
2011-01-29 00:59:50 +00:00
m_DDRaceState = DDRACE_NONE;
m_PrevPos = m_Pos;
m_SetSavePos = false;
2011-01-29 00:59:50 +00:00
m_LastBroadcast = 0;
m_TeamBeforeSuper = 0;
m_Core.m_Id = GetPlayer()->GetCID();
m_TeleCheckpoint = 0;
2011-07-22 12:29:27 +00:00
m_EndlessHook = g_Config.m_SvEndlessDrag;
m_Hit = g_Config.m_SvHit ? HIT_ALL : DISABLE_HIT_GRENADE|DISABLE_HIT_HAMMER|DISABLE_HIT_LASER|DISABLE_HIT_SHOTGUN;
m_SuperJump = false;
2013-11-22 14:10:55 +00:00
m_Jetpack = false;
m_Core.m_Jumps = 2;
m_FreezeHammer = false;
2013-11-15 23:44:49 +00:00
int Team = Teams()->m_Core.Team(m_Core.m_Id);
if(Teams()->TeamLocked(Team))
{
for (int i = 0; i < MAX_CLIENTS; i++)
{
if(Teams()->m_Core.Team(i) == Team && i != m_Core.m_Id && GameServer()->m_apPlayers[i])
2013-11-15 23:44:49 +00:00
{
CCharacter* pChar = GameServer()->m_apPlayers[i]->GetCharacter();
if (pChar)
{
m_DDRaceState = pChar->m_DDRaceState;
m_StartTime = pChar->m_StartTime;
}
}
}
}
if(g_Config.m_SvTeam == 2 && Team == TEAM_FLOCK)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"Please join a team before you start");
m_LastStartWarning = Server()->Tick();
}
}
void CCharacter::Rescue()
{
if (m_SetSavePos && !m_Super) {
if (m_LastRescue + g_Config.m_SvRescueDelay * Server()->TickSpeed() > Server()->Tick())
{
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "You have to wait %d seconds until you can rescue yourself", (int)((m_LastRescue + g_Config.m_SvRescueDelay * Server()->TickSpeed() - Server()->Tick()) / Server()->TickSpeed()));
GameServer()->SendChatTarget(GetPlayer()->GetCID(), aBuf);
return;
}
if (m_DeepFreeze || m_FreezeTime) {
m_LastRescue = Server()->Tick();
2015-04-16 16:13:36 +00:00
m_Core.m_Pos = m_PrevSavePos;
m_Pos = m_PrevSavePos;
m_PrevPos = m_PrevSavePos;
m_Core.m_Vel = vec2(0, 0);
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
GameWorld()->ReleaseHooked(GetPlayer()->GetCID());
m_Core.m_HookPos = m_Core.m_Pos;
m_DeepFreeze = false;
2015-04-16 16:13:36 +00:00
UnFreeze();
for(int i = 0; i< NUM_WEAPONS; i++)
{
m_aWeapons[i].m_AmmoRegenStart = m_aPrevSaveWeapons[i].m_AmmoRegenStart;
m_aWeapons[i].m_Ammo = m_aPrevSaveWeapons[i].m_Ammo;
m_aWeapons[i].m_Ammocost = m_aPrevSaveWeapons[i].m_Ammocost;
m_aWeapons[i].m_Got = m_aPrevSaveWeapons[i].m_Got;
}
}
}
}