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

1615 lines
67 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>
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 <stdio.h>
#include <string.h>
#include <engine/server/server.h>
#include <game/server/gamemodes/DDRace.h>
#include <game/server/score.h>
#include "light.h"
2010-05-29 07:25:38 +00:00
//input count
struct CInputCount
{
2010-05-29 07:25:38 +00:00
int m_Presses;
int m_Releases;
};
2010-05-29 07:25:38 +00:00
CInputCount CountInput(int Prev, int Cur)
{
2010-05-29 07:25:38 +00:00
CInputCount c = {0, 0};
Prev &= INPUT_STATE_MASK;
Cur &= INPUT_STATE_MASK;
int i = Prev;
2010-05-29 07:25:38 +00:00
while(i != Cur)
{
i = (i+1)&INPUT_STATE_MASK;
if(i&1)
2010-05-29 07:25:38 +00:00
c.m_Presses++;
else
2010-05-29 07:25:38 +00:00
c.m_Releases++;
}
return c;
}
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;
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_ActiveWeapon = WEAPON_GUN;
m_LastWeapon = WEAPON_HAMMER;
m_QueuedWeapon = -1;
2010-05-29 07:25:38 +00:00
m_pPlayer = pPlayer;
m_Pos = Pos;
2010-05-29 07:25:38 +00:00
m_Core.Reset();
2011-01-29 00:59:50 +00:00
m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision(), &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core);
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
DDRaceInit();
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;
}
2010-05-29 07:25:38 +00:00
void CCharacter::SetWeapon(int W)
{
2010-05-29 07:25:38 +00:00
if(W == m_ActiveWeapon)
return;
2010-05-29 07:25:38 +00:00
m_LastWeapon = m_ActiveWeapon;
m_QueuedWeapon = -1;
m_ActiveWeapon = W;
GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
2010-05-29 07:25:38 +00:00
if(m_ActiveWeapon < 0 || m_ActiveWeapon >= NUM_WEAPONS)
m_ActiveWeapon = 0;
}
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;
return false;
}
2010-05-29 07:25:38 +00:00
void CCharacter::HandleNinja()
{
2010-05-29 07:25:38 +00:00
if(m_ActiveWeapon != WEAPON_NINJA)
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
2010-05-29 07:25:38 +00:00
m_aWeapons[WEAPON_NINJA].m_Got = false;
m_ActiveWeapon = m_LastWeapon;
2010-05-29 07:25:38 +00:00
SetWeapon(m_ActiveWeapon);
return;
}
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;
2010-06-03 15:39:42 +00:00
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);
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;
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)
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()
{
2010-05-29 07:25:38 +00:00
int WantedWeapon = m_ActiveWeapon;
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
2010-05-29 07:25:38 +00:00
if(WantedWeapon >= 0 && WantedWeapon < NUM_WEAPONS && WantedWeapon != m_ActiveWeapon && m_aWeapons[WantedWeapon].m_Got)
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)
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_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE)
FullAuto = true;
// 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;
2010-05-29 07:25:38 +00:00
if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo)
WillFire = true;
2010-05-29 07:25:38 +00:00
if(!WillFire)
return;
// check for ammo
2010-05-29 07:25:38 +00:00
if(!m_aWeapons[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);*/
// 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;
}
2010-06-03 15:39:42 +00:00
vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f;
2010-05-29 07:25:38 +00:00
switch(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()));
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))
if((pTarget == this || !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,
m_pPlayer->GetCID(), m_ActiveWeapon);*/
vec2 Temp = pTarget->m_Core.m_Vel + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f;
if(Temp.x > 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_270) || (pTarget->m_TileIndexL == TILE_STOP && pTarget->m_TileFlagsL == ROTATION_270) || (pTarget->m_TileIndexL == TILE_STOPS && (pTarget->m_TileFlagsL == ROTATION_90 || pTarget->m_TileFlagsL ==ROTATION_270)) || (pTarget->m_TileIndexL == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_270) || (pTarget->m_TileFIndexL == TILE_STOP && pTarget->m_TileFFlagsL == ROTATION_270) || (pTarget->m_TileFIndexL == TILE_STOPS && (pTarget->m_TileFFlagsL == ROTATION_90 || pTarget->m_TileFFlagsL == ROTATION_270)) || (pTarget->m_TileFIndexL == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_270) || (pTarget->m_TileSIndexL == TILE_STOP && pTarget->m_TileSFlagsL == ROTATION_270) || (pTarget->m_TileSIndexL == TILE_STOPS && (pTarget->m_TileSFlagsL == ROTATION_90 || pTarget->m_TileSFlagsL == ROTATION_270)) || (pTarget->m_TileSIndexL == TILE_STOPA)))
Temp.x = 0;
if(Temp.x < 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_90) || (pTarget->m_TileIndexR == TILE_STOP && pTarget->m_TileFlagsR == ROTATION_90) || (pTarget->m_TileIndexR == TILE_STOPS && (pTarget->m_TileFlagsR == ROTATION_90 || pTarget->m_TileFlagsR == ROTATION_270)) || (pTarget->m_TileIndexR == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_90) || (pTarget->m_TileFIndexR == TILE_STOP && pTarget->m_TileFFlagsR == ROTATION_90) || (pTarget->m_TileFIndexR == TILE_STOPS && (pTarget->m_TileFFlagsR == ROTATION_90 || pTarget->m_TileFFlagsR == ROTATION_270)) || (pTarget->m_TileFIndexR == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_90) || (pTarget->m_TileSIndexR == TILE_STOP && pTarget->m_TileSFlagsR == ROTATION_90) || (pTarget->m_TileSIndexR == TILE_STOPS && (pTarget->m_TileSFlagsR == ROTATION_90 || pTarget->m_TileSFlagsR == ROTATION_270)) || (pTarget->m_TileSIndexR == TILE_STOPA)))
Temp.x = 0;
if(Temp.y < 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_180) || (pTarget->m_TileIndexB == TILE_STOP && pTarget->m_TileFlagsB == ROTATION_180) || (pTarget->m_TileIndexB == TILE_STOPS && (pTarget->m_TileFlagsB == ROTATION_0 || pTarget->m_TileFlagsB == ROTATION_180)) || (pTarget->m_TileIndexB == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_180) || (pTarget->m_TileFIndexB == TILE_STOP && pTarget->m_TileFFlagsB == ROTATION_180) || (pTarget->m_TileFIndexB == TILE_STOPS && (pTarget->m_TileFFlagsB == ROTATION_0 || pTarget->m_TileFFlagsB == ROTATION_180)) || (pTarget->m_TileFIndexB == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_180) || (pTarget->m_TileSIndexB == TILE_STOP && pTarget->m_TileSFlagsB == ROTATION_180) || (pTarget->m_TileSIndexB == TILE_STOPS && (pTarget->m_TileSFlagsB == ROTATION_0 || pTarget->m_TileSFlagsB == ROTATION_180)) || (pTarget->m_TileSIndexB == TILE_STOPA)))
Temp.y = 0;
if(Temp.y > 0 && ((pTarget->m_TileIndex == TILE_STOP && pTarget->m_TileFlags == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOP && pTarget->m_TileFlagsT == ROTATION_0) || (pTarget->m_TileIndexT == TILE_STOPS && (pTarget->m_TileFlagsT == ROTATION_0 || pTarget->m_TileFlagsT == ROTATION_180)) || (pTarget->m_TileIndexT == TILE_STOPA) || (pTarget->m_TileFIndex == TILE_STOP && pTarget->m_TileFFlags == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOP && pTarget->m_TileFFlagsT == ROTATION_0) || (pTarget->m_TileFIndexT == TILE_STOPS && (pTarget->m_TileFFlagsT == ROTATION_0 || pTarget->m_TileFFlagsT == ROTATION_180)) || (pTarget->m_TileFIndexT == TILE_STOPA) || (pTarget->m_TileSIndex == TILE_STOP && pTarget->m_TileSFlags == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOP && pTarget->m_TileSFlagsT == ROTATION_0) || (pTarget->m_TileSIndexT == TILE_STOPS && (pTarget->m_TileSFlagsT == ROTATION_0 || pTarget->m_TileSFlagsT == ROTATION_180)) || (pTarget->m_TileSIndexT == TILE_STOPA)))
Temp.y = 0;
Temp -= pTarget->m_Core.m_Vel;
pTarget->TakeDamage(vec2(0.f, -1.f) + Temp, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage,
m_pPlayer->GetCID(), m_ActiveWeapon);
pTarget->UnFreeze();
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:
{
CProjectile *pProj = new CProjectile
(
GameWorld(),
WEAPON_GUN,//Type
m_pPlayer->GetCID(),//Owner
ProjStartPos,//Pos
Direction,//Dir
(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime),//Span
0,//Freeze
0,//Explosive
0,//Force
-1,//SoundImpact
WEAPON_GUN//Weapon
);
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
CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
Msg.AddInt(1);
for(unsigned i = 0; i < sizeof(CNetObj_Projectile)/sizeof(int); i++)
Msg.AddInt(((int *)&p)[i]);
2010-05-29 07:25:38 +00:00
Server()->SendMsg(&Msg, 0, m_pPlayer->GetCID());
GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
} 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, WEAPON_SHOTGUN);
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, 0,m_pPlayer->GetCID());
GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE);*/
new CLaser(&GameServer()->m_World, m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID(), WEAPON_SHOTGUN);
GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
} break;
case WEAPON_GRENADE:
{
2011-01-29 00:59:50 +00:00
CProjectile *pProj = new CProjectile
(
GameWorld(),
WEAPON_GRENADE,//Type
m_pPlayer->GetCID(),//Owner
ProjStartPos,//Pos
Direction,//Dir
(int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GrenadeLifetime),//Span
0,//Freeze
true,//Explosive
0,//Force
SOUND_GRENADE_EXPLODE,//SoundImpact
WEAPON_GRENADE//Weapon
);//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, 0, m_pPlayer->GetCID());
GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE, Teams()->TeamMask(Team(), -1, m_pPlayer->GetCID()));
} break;
case WEAPON_RIFLE:
{
new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID(), WEAPON_RIFLE);
GameServer()->CreateSound(m_Pos, SOUND_RIFLE_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();
/*if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0) // -1 == unlimited
m_aWeapons[m_ActiveWeapon].m_Ammo--;*/
2010-05-29 07:25:38 +00:00
if(!m_ReloadTimer)
m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_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();
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
2010-05-29 07:25:38 +00:00
int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime;
if(AmmoRegenTime)
{
// If equipped and not active, regen ammo?
2010-05-29 07:25:38 +00:00
if (m_ReloadTimer <= 0)
{
2010-05-29 07:25:38 +00:00
if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0)
m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick();
2010-05-29 07:25:38 +00:00
if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000)
{
// Add some ammo
2010-05-29 07:25:38 +00:00
m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, 10);
m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1;
}
}
else
{
2010-05-29 07:25:38 +00:00
m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1;
}
}*/
2010-05-29 07:25:38 +00:00
return;
}
bool CCharacter::GiveWeapon(int Weapon, int Ammo)
{
if(m_aWeapons[Weapon].m_Ammo < g_pData->m_Weapons.m_aId[Weapon].m_Maxammo || !m_aWeapons[Weapon].m_Got)
{
2010-05-29 07:25:38 +00:00
m_aWeapons[Weapon].m_Got = true;
if(!m_FreezeTime)
m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, Ammo);
2010-05-29 07:25:38 +00:00
return true;
}
return false;
}
void CCharacter::GiveNinja()
{
m_Ninja.m_ActivationTick = Server()->Tick();
m_aWeapons[WEAPON_NINJA].m_Got = true;
if (!m_FreezeTime)
m_aWeapons[WEAPON_NINJA].m_Ammo = -1;
if (m_ActiveWeapon != WEAPON_NINJA)
m_LastWeapon = m_ActiveWeapon;
2010-05-29 07:25:38 +00:00
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()));
}
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
2010-05-29 07:25:38 +00:00
if(mem_comp(&m_Input, pNewInput, sizeof(CNetObj_PlayerInput)) != 0)
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;
}
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;
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();
}
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;
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();
2011-01-29 00:59:50 +00:00
m_Core.m_Input = m_Input;
m_Core.Tick(true);
/*// handle death-tiles and leaving gamelayer
2011-01-29 00:59:50 +00:00
if(GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameLayerClipped(m_Pos))
{
Die(m_pPlayer->GetCID(), WEAPON_WORLD);
}*/
2011-01-29 00:59:50 +00:00
// handle Weapons
HandleWeapons();
DDRacePostCoreTick();
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(), &((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.m_Core);
m_ReckoningCore.m_Id = m_pPlayer->GetCID();
2011-01-29 00:59:50 +00:00
m_ReckoningCore.Tick(false);
m_ReckoningCore.Move();
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();
2011-01-29 00:59:50 +00:00
m_Core.Move();
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;
}
}
}
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)
{
2011-03-26 21:38:05 +00:00
// we got to wait 0.5 secs before respawning
m_pPlayer->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
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()));
2011-01-29 00:59:50 +00:00
// this is for auto respawn after 3 secs
m_pPlayer->m_DieTick = Server()->Tick();
2011-01-29 00:59:50 +00:00
m_Alive = 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()->SetForceCharacterTeam(m_pPlayer->GetCID(), 0);
2011-01-29 00:59:50 +00:00
}
bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
{
/*m_Core.m_Vel += Force;
2011-01-29 00:59:50 +00:00
if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From) && !g_Config.m_SvTeamdamage)
return false;
// m_pPlayer only inflicts half damage on self
if(From == m_pPlayer->GetCID())
Dmg = max(1, Dmg/2);
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])
{
int 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);*/
2011-01-29 00:59:50 +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;
if(Temp.x > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_270) || (m_TileIndexL == TILE_STOP && m_TileFlagsL == ROTATION_270) || (m_TileIndexL == TILE_STOPS && (m_TileFlagsL == ROTATION_90 || m_TileFlagsL ==ROTATION_270)) || (m_TileIndexL == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_270) || (m_TileFIndexL == TILE_STOP && m_TileFFlagsL == ROTATION_270) || (m_TileFIndexL == TILE_STOPS && (m_TileFFlagsL == ROTATION_90 || m_TileFFlagsL == ROTATION_270)) || (m_TileFIndexL == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_270) || (m_TileSIndexL == TILE_STOP && m_TileSFlagsL == ROTATION_270) || (m_TileSIndexL == TILE_STOPS && (m_TileSFlagsL == ROTATION_90 || m_TileSFlagsL == ROTATION_270)) || (m_TileSIndexL == TILE_STOPA)))
Temp.x = 0;
if(Temp.x < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_90) || (m_TileIndexR == TILE_STOP && m_TileFlagsR == ROTATION_90) || (m_TileIndexR == TILE_STOPS && (m_TileFlagsR == ROTATION_90 || m_TileFlagsR == ROTATION_270)) || (m_TileIndexR == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_90) || (m_TileFIndexR == TILE_STOP && m_TileFFlagsR == ROTATION_90) || (m_TileFIndexR == TILE_STOPS && (m_TileFFlagsR == ROTATION_90 || m_TileFFlagsR == ROTATION_270)) || (m_TileFIndexR == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_90) || (m_TileSIndexR == TILE_STOP && m_TileSFlagsR == ROTATION_90) || (m_TileSIndexR == TILE_STOPS && (m_TileSFlagsR == ROTATION_90 || m_TileSFlagsR == ROTATION_270)) || (m_TileSIndexR == TILE_STOPA)))
Temp.x = 0;
if(Temp.y < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_180) || (m_TileIndexB == TILE_STOP && m_TileFlagsB == ROTATION_180) || (m_TileIndexB == TILE_STOPS && (m_TileFlagsB == ROTATION_0 || m_TileFlagsB == ROTATION_180)) || (m_TileIndexB == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_180) || (m_TileFIndexB == TILE_STOP && m_TileFFlagsB == ROTATION_180) || (m_TileFIndexB == TILE_STOPS && (m_TileFFlagsB == ROTATION_0 || m_TileFFlagsB == ROTATION_180)) || (m_TileFIndexB == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_180) || (m_TileSIndexB == TILE_STOP && m_TileSFlagsB == ROTATION_180) || (m_TileSIndexB == TILE_STOPS && (m_TileSFlagsB == ROTATION_0 || m_TileSFlagsB == ROTATION_180)) || (m_TileSIndexB == TILE_STOPA)))
Temp.y = 0;
if(Temp.y > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_0) || (m_TileIndexT == TILE_STOP && m_TileFlagsT == ROTATION_0) || (m_TileIndexT == TILE_STOPS && (m_TileFlagsT == ROTATION_0 || m_TileFlagsT == ROTATION_180)) || (m_TileIndexT == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_0) || (m_TileFIndexT == TILE_STOP && m_TileFFlagsT == ROTATION_0) || (m_TileFIndexT == TILE_STOPS && (m_TileFFlagsT == ROTATION_0 || m_TileFFlagsT == ROTATION_180)) || (m_TileFIndexT == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_0) || (m_TileSIndexT == TILE_STOP && m_TileSFlagsT == ROTATION_0) || (m_TileSIndexT == TILE_STOPS && (m_TileSFlagsT == ROTATION_0 || m_TileSFlagsT == ROTATION_180)) || (m_TileSIndexT == TILE_STOPA)))
Temp.y = 0;
m_Core.m_Vel = Temp;
2011-01-29 00:59:50 +00:00
return true;
}
void CCharacter::Snap(int SnappingClient)
{
if(NetworkClipped(SnappingClient))
return;
2011-01-29 00:59:50 +00:00
CCharacter* SnapChar = GameServer()->GetPlayerChar(SnappingClient);
if(SnapChar && !SnapChar->m_Super && !SnapChar->IsPaused() &&
2011-01-29 00:59:50 +00:00
GameServer()->m_apPlayers[SnappingClient]->GetTeam() != -1 &&
!CanCollide(SnappingClient) &&
(!GameServer()->m_apPlayers[SnappingClient]->m_IsUsingDDRaceClient ||
(GameServer()->m_apPlayers[SnappingClient]->m_IsUsingDDRaceClient &&
!GameServer()->m_apPlayers[SnappingClient]->m_ShowOthers
)
)
)
return;
if (m_Paused)
return;
2011-01-29 00:59:50 +00:00
CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character)));
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;
}
pCharacter->m_Emote = m_EmoteType;
pCharacter->m_AmmoCount = 0;
pCharacter->m_Health = 0;
pCharacter->m_Armor = 0;
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;
pCharacter->m_AmmoCount = 0;
}
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;
pCharacter->m_AmmoCount = 0;
}
else
pCharacter->m_Weapon = m_ActiveWeapon;
pCharacter->m_AttackTick = m_AttackTick;
pCharacter->m_Direction = m_Input.m_Direction;
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;
if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0)
//pCharacter->m_AmmoCount = m_aWeapons[m_ActiveWeapon].m_Ammo;
2011-01-29 00:59:50 +00:00
pCharacter->m_AmmoCount = (!m_FreezeTime)?m_aWeapons[m_ActiveWeapon].m_Ammo:0;
}
if(pCharacter->m_Emote == EMOTE_NORMAL)
{
if(250 - ((Server()->Tick() - m_LastAction)%(250)) < 5)
pCharacter->m_Emote = EMOTE_BLINK;
}
pCharacter->m_PlayerFlags = GetPlayer()->m_PlayerFlags;
2011-01-29 00:59:50 +00:00
}
// 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
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());
2011-06-05 11:56:04 +00:00
if((m_DDRaceState == DDRACE_STARTED && Server()->Tick() - m_RefreshTime >= Server()->TickSpeed()) &&
m_CpActive != -1 && m_CpTick > Server()->Tick() && !m_pPlayer->m_IsUsingDDRaceClient &&
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];
m_Time = (float)(Server()->Tick() - m_StartTime) / ((float)Server()->TickSpeed());
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());
m_LastBroadcast = Server()->Tick();
}
else if (m_pPlayer->m_BroadcastTime && 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);
GameServer()->SendBroadcast(aBuftime, m_pPlayer->GetCID());
m_LastBroadcast = Server()->Tick();
}
2011-06-05 11:56:04 +00:00
m_RefreshTime = 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
if((GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetFCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
GameLayerClipped(m_Pos)) &&
2011-08-31 21:36:41 +00:00
!m_Super && !(Team() && Teams()->TeeFinished(m_pPlayer->GetCID())))
{
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;
//dbg_msg("speedup tile start","Direction %f %f, Force %d, Max Speed %d", (Direction).x,(Direction).y, Force, MaxSpeed);
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;
//dbg_msg("speedup tile debug","MaxSpeed %i, TeeSpeed %f, SpeedLeft %f, SpeederAngle %f, TeeAngle %f", MaxSpeed, TeeSpeed, SpeedLeft, SpeederAngle, TeeAngle);
if(abs(SpeedLeft) > Force && SpeedLeft > 0.0000001f)
TempVel += Direction * Force;
else if(abs(SpeedLeft) > Force)
TempVel += Direction * -Force;
else
TempVel += Direction * SpeedLeft;
}
else
TempVel += Direction * Force;
if(TempVel.x > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_270) || (m_TileIndexL == TILE_STOP && m_TileFlagsL == ROTATION_270) || (m_TileIndexL == TILE_STOPS && (m_TileFlagsL == ROTATION_90 || m_TileFlagsL ==ROTATION_270)) || (m_TileIndexL == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_270) || (m_TileFIndexL == TILE_STOP && m_TileFFlagsL == ROTATION_270) || (m_TileFIndexL == TILE_STOPS && (m_TileFFlagsL == ROTATION_90 || m_TileFFlagsL == ROTATION_270)) || (m_TileFIndexL == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_270) || (m_TileSIndexL == TILE_STOP && m_TileSFlagsL == ROTATION_270) || (m_TileSIndexL == TILE_STOPS && (m_TileSFlagsL == ROTATION_90 || m_TileSFlagsL == ROTATION_270)) || (m_TileSIndexL == TILE_STOPA)))
TempVel.x = 0;
if(TempVel.x < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_90) || (m_TileIndexR == TILE_STOP && m_TileFlagsR == ROTATION_90) || (m_TileIndexR == TILE_STOPS && (m_TileFlagsR == ROTATION_90 || m_TileFlagsR == ROTATION_270)) || (m_TileIndexR == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_90) || (m_TileFIndexR == TILE_STOP && m_TileFFlagsR == ROTATION_90) || (m_TileFIndexR == TILE_STOPS && (m_TileFFlagsR == ROTATION_90 || m_TileFFlagsR == ROTATION_270)) || (m_TileFIndexR == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_90) || (m_TileSIndexR == TILE_STOP && m_TileSFlagsR == ROTATION_90) || (m_TileSIndexR == TILE_STOPS && (m_TileSFlagsR == ROTATION_90 || m_TileSFlagsR == ROTATION_270)) || (m_TileSIndexR == TILE_STOPA)))
TempVel.x = 0;
if(TempVel.y < 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_180) || (m_TileIndexB == TILE_STOP && m_TileFlagsB == ROTATION_180) || (m_TileIndexB == TILE_STOPS && (m_TileFlagsB == ROTATION_0 || m_TileFlagsB == ROTATION_180)) || (m_TileIndexB == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_180) || (m_TileFIndexB == TILE_STOP && m_TileFFlagsB == ROTATION_180) || (m_TileFIndexB == TILE_STOPS && (m_TileFFlagsB == ROTATION_0 || m_TileFFlagsB == ROTATION_180)) || (m_TileFIndexB == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_180) || (m_TileSIndexB == TILE_STOP && m_TileSFlagsB == ROTATION_180) || (m_TileSIndexB == TILE_STOPS && (m_TileSFlagsB == ROTATION_0 || m_TileSFlagsB == ROTATION_180)) || (m_TileSIndexB == TILE_STOPA)))
TempVel.y = 0;
if(TempVel.y > 0 && ((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_0) || (m_TileIndexT == TILE_STOP && m_TileFlagsT == ROTATION_0) || (m_TileIndexT == TILE_STOPS && (m_TileFlagsT == ROTATION_0 || m_TileFlagsT == ROTATION_180)) || (m_TileIndexT == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_0) || (m_TileFIndexT == TILE_STOP && m_TileFFlagsT == ROTATION_0) || (m_TileFIndexT == TILE_STOPS && (m_TileFFlagsT == ROTATION_0 || m_TileFFlagsT == ROTATION_180)) || (m_TileFIndexT == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_0) || (m_TileSIndexT == TILE_STOP && m_TileSFlagsT == ROTATION_0) || (m_TileSIndexT == TILE_STOPS && (m_TileSFlagsT == ROTATION_0 || m_TileSFlagsT == ROTATION_180)) || (m_TileSIndexT == TILE_STOPA)))
TempVel.y = 0;
m_Core.m_Vel = TempVel;
//dbg_msg("speedup tile end","(Direction*Force) %f %f m_Core.m_Vel%f %f",(Direction*Force).x,(Direction*Force).y,m_Core.m_Vel.x,m_Core.m_Vel.y);
//dbg_msg("speedup tile end","Direction %f %f, Force %d, Max Speed %d", (Direction).x,(Direction).y, Force, MaxSpeed);
}
}
}
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);
float Offset = 4.0f;
int MapIndexL = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x + (m_ProximityRadius / 2) + Offset, m_Pos.y));
int MapIndexR = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x - (m_ProximityRadius / 2) - Offset, m_Pos.y));
int MapIndexT = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x, m_Pos.y + (m_ProximityRadius / 2) + Offset));
int MapIndexB = GameServer()->Collision()->GetPureMapIndex(vec2(m_Pos.x, m_Pos.y - (m_ProximityRadius / 2) - Offset));
2010-10-08 13:33:42 +00:00
//dbg_msg("","N%d L%d R%d B%d T%d",MapIndex,MapIndexL,MapIndexR,MapIndexB,MapIndexT);
m_TileIndex = GameServer()->Collision()->GetTileIndex(MapIndex);
2010-11-01 01:51:17 +00:00
m_TileFlags = GameServer()->Collision()->GetTileFlags(MapIndex);
2010-10-08 13:33:42 +00:00
m_TileIndexL = GameServer()->Collision()->GetTileIndex(MapIndexL);
2010-11-01 01:51:17 +00:00
m_TileFlagsL = GameServer()->Collision()->GetTileFlags(MapIndexL);
2010-10-08 13:33:42 +00:00
m_TileIndexR = GameServer()->Collision()->GetTileIndex(MapIndexR);
2010-11-01 01:51:17 +00:00
m_TileFlagsR = GameServer()->Collision()->GetTileFlags(MapIndexR);
2010-10-08 13:33:42 +00:00
m_TileIndexB = GameServer()->Collision()->GetTileIndex(MapIndexB);
2010-11-01 01:51:17 +00:00
m_TileFlagsB = GameServer()->Collision()->GetTileFlags(MapIndexB);
2010-10-08 13:33:42 +00:00
m_TileIndexT = GameServer()->Collision()->GetTileIndex(MapIndexT);
2010-11-01 01:51:17 +00:00
m_TileFlagsT = GameServer()->Collision()->GetTileFlags(MapIndexT);
2010-10-08 13:33:42 +00:00
m_TileFIndex = GameServer()->Collision()->GetFTileIndex(MapIndex);
2010-11-01 01:51:17 +00:00
m_TileFFlags = GameServer()->Collision()->GetFTileFlags(MapIndex);
2010-10-08 13:33:42 +00:00
m_TileFIndexL = GameServer()->Collision()->GetFTileIndex(MapIndexL);
2010-11-01 01:51:17 +00:00
m_TileFFlagsL = GameServer()->Collision()->GetFTileFlags(MapIndexL);
2010-10-08 13:33:42 +00:00
m_TileFIndexR = GameServer()->Collision()->GetFTileIndex(MapIndexR);
2010-11-01 01:51:17 +00:00
m_TileFFlagsR = GameServer()->Collision()->GetFTileFlags(MapIndexR);
2010-10-08 13:33:42 +00:00
m_TileFIndexB = GameServer()->Collision()->GetFTileIndex(MapIndexB);
2010-11-01 01:51:17 +00:00
m_TileFFlagsB = GameServer()->Collision()->GetFTileFlags(MapIndexB);
2010-10-08 13:33:42 +00:00
m_TileFIndexT = GameServer()->Collision()->GetFTileIndex(MapIndexT);
m_TileFFlagsT = GameServer()->Collision()->GetFTileFlags(MapIndexT);//
m_TileSIndex = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndex)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileIndex(MapIndex) : 0 : 0;
m_TileSFlags = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndex)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileFlags(MapIndex) : 0 : 0;
m_TileSIndexL = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexL)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileIndex(MapIndexL) : 0 : 0;
m_TileSFlagsL = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexL)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileFlags(MapIndexL) : 0 : 0;
m_TileSIndexR = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexR)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileIndex(MapIndexR) : 0 : 0;
m_TileSFlagsR = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexR)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileFlags(MapIndexR) : 0 : 0;
m_TileSIndexB = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexB)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileIndex(MapIndexB) : 0 : 0;
m_TileSFlagsB = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexB)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileFlags(MapIndexB) : 0 : 0;
m_TileSIndexT = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexT)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileIndex(MapIndexT) : 0 : 0;
m_TileSFlagsT = (GameServer()->Collision()->m_pSwitchers && GameServer()->Collision()->m_pSwitchers[GameServer()->Collision()->GetDTileNumber(MapIndexT)].m_Status[Team()])?(Team() != TEAM_SUPER)? GameServer()->Collision()->GetDTileFlags(MapIndexT) : 0 : 0;
//dbg_msg("Tiles","%d, %d, %d, %d, %d", m_TileSIndex, m_TileSIndexL, m_TileSIndexR, m_TileSIndexB, m_TileSIndexT);
//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);
2010-10-08 13:33:42 +00:00
//dbg_msg("","N%d L%d R%d B%d T%d",m_TileIndex,m_TileIndexL,m_TileIndexR,m_TileIndexB,m_TileIndexT);
//dbg_msg("","N%d L%d R%d B%d T%d",m_TileFIndex,m_TileFIndexL,m_TileFIndexR,m_TileFIndexB,m_TileFIndexT);
2011-02-01 12:01:05 +00:00
if(Index < 0)
return;
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;
2010-11-30 02:24:15 +00:00
if(m_pPlayer->m_IsUsingDDRaceClient) {
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;
2010-11-30 02:24:15 +00:00
if(m_pPlayer->m_IsUsingDDRaceClient) {
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;
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())))
2010-10-08 13:33:42 +00:00
{
2010-11-06 22:54:35 +00:00
bool CanBegin = true;
if(g_Config.m_SvResetPickus)
{
for (int i = WEAPON_SHOTGUN; i < NUM_WEAPONS; ++i)
{
m_aWeapons[i].m_Got = false;
if(m_ActiveWeapon == i)
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())
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"Server admin requires you to be in a team and with other tees to start");
m_LastStartWarning = Server()->Tick();
}
2010-11-06 22:54:35 +00:00
CanBegin = false;
}
2011-01-29 14:31:50 +00:00
if(CanBegin)
{
2011-02-14 21:34:46 +00:00
Teams()->OnCharacterStart(m_pPlayer->GetCID());
2010-11-06 22:54:35 +00:00
m_CpActive = -2;
} else {
2010-11-06 22:54:35 +00:00
}
2010-10-08 13:33:42 +00:00
}
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());
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();
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;
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;
}
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;
}
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;
}
else if(((m_TileIndex == TILE_HIT_END) || (m_TileFIndex == TILE_HIT_END)) && m_Hit != (DISABLE_HIT_GRENADE|DISABLE_HIT_HAMMER|DISABLE_HIT_RIFLE|DISABLE_HIT_SHOTGUN))
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You can't hit others");
m_Hit = DISABLE_HIT_GRENADE|DISABLE_HIT_HAMMER|DISABLE_HIT_RIFLE|DISABLE_HIT_SHOTGUN;
}
if(((m_TileIndex == TILE_SOLO_START) || (m_TileFIndex == TILE_SOLO_START)) && !Teams()->m_Core.GetSolo(m_pPlayer->GetCID()))
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You are now in a solo part.");
Teams()->m_Core.SetSolo(m_pPlayer->GetCID(), true);
}
else if(((m_TileIndex == TILE_SOLO_END) || (m_TileFIndex == TILE_SOLO_END)) && Teams()->m_Core.GetSolo(m_pPlayer->GetCID()))
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(), "You are now out of the solo part.");
Teams()->m_Core.SetSolo(m_pPlayer->GetCID(), false);
}
2011-02-07 02:22:13 +00:00
if(((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_270) || (m_TileIndexL == TILE_STOP && m_TileFlagsL == ROTATION_270) || (m_TileIndexL == TILE_STOPS && (m_TileFlagsL == ROTATION_90 || m_TileFlagsL ==ROTATION_270)) || (m_TileIndexL == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_270) || (m_TileFIndexL == TILE_STOP && m_TileFFlagsL == ROTATION_270) || (m_TileFIndexL == TILE_STOPS && (m_TileFFlagsL == ROTATION_90 || m_TileFFlagsL == ROTATION_270)) || (m_TileFIndexL == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_270) || (m_TileSIndexL == TILE_STOP && m_TileSFlagsL == ROTATION_270) || (m_TileSIndexL == TILE_STOPS && (m_TileSFlagsL == ROTATION_90 || m_TileSFlagsL == ROTATION_270)) || (m_TileSIndexL == TILE_STOPA)) && m_Core.m_Vel.x > 0)
2010-10-08 13:33:42 +00:00
{
2011-02-07 02:22:13 +00:00
if((int)GameServer()->Collision()->GetPos(MapIndexL).x)
if((int)GameServer()->Collision()->GetPos(MapIndexL).x < (int)m_Core.m_Pos.x)
m_Core.m_Pos = m_PrevPos;
2011-02-07 02:22:13 +00:00
m_Core.m_Vel.x = 0;
2010-10-08 13:33:42 +00:00
}
2011-02-07 02:22:13 +00:00
if(((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_90) || (m_TileIndexR == TILE_STOP && m_TileFlagsR == ROTATION_90) || (m_TileIndexR == TILE_STOPS && (m_TileFlagsR == ROTATION_90 || m_TileFlagsR == ROTATION_270)) || (m_TileIndexR == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_90) || (m_TileFIndexR == TILE_STOP && m_TileFFlagsR == ROTATION_90) || (m_TileFIndexR == TILE_STOPS && (m_TileFFlagsR == ROTATION_90 || m_TileFFlagsR == ROTATION_270)) || (m_TileFIndexR == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_90) || (m_TileSIndexR == TILE_STOP && m_TileSFlagsR == ROTATION_90) || (m_TileSIndexR == TILE_STOPS && (m_TileSFlagsR == ROTATION_90 || m_TileSFlagsR == ROTATION_270)) || (m_TileSIndexR == TILE_STOPA)) && m_Core.m_Vel.x < 0)
2010-10-08 13:33:42 +00:00
{
2011-02-07 02:22:13 +00:00
if((int)GameServer()->Collision()->GetPos(MapIndexR).x)
if((int)GameServer()->Collision()->GetPos(MapIndexR).x > (int)m_Core.m_Pos.x)
m_Core.m_Pos = m_PrevPos;
2011-02-07 02:22:13 +00:00
m_Core.m_Vel.x = 0;
2010-10-08 13:33:42 +00:00
}
2011-02-07 02:22:13 +00:00
if(((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_180) || (m_TileIndexB == TILE_STOP && m_TileFlagsB == ROTATION_180) || (m_TileIndexB == TILE_STOPS && (m_TileFlagsB == ROTATION_0 || m_TileFlagsB == ROTATION_180)) || (m_TileIndexB == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_180) || (m_TileFIndexB == TILE_STOP && m_TileFFlagsB == ROTATION_180) || (m_TileFIndexB == TILE_STOPS && (m_TileFFlagsB == ROTATION_0 || m_TileFFlagsB == ROTATION_180)) || (m_TileFIndexB == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_180) || (m_TileSIndexB == TILE_STOP && m_TileSFlagsB == ROTATION_180) || (m_TileSIndexB == TILE_STOPS && (m_TileSFlagsB == ROTATION_0 || m_TileSFlagsB == ROTATION_180)) || (m_TileSIndexB == TILE_STOPA)) && m_Core.m_Vel.y < 0)
2010-10-08 13:33:42 +00:00
{
2011-02-07 02:22:13 +00:00
if((int)GameServer()->Collision()->GetPos(MapIndexB).y)
if((int)GameServer()->Collision()->GetPos(MapIndexB).y > (int)m_Core.m_Pos.y)
m_Core.m_Pos = m_PrevPos;
2011-02-07 02:22:13 +00:00
m_Core.m_Vel.y = 0;
2010-10-08 13:33:42 +00:00
}
2011-02-07 02:22:13 +00:00
if(((m_TileIndex == TILE_STOP && m_TileFlags == ROTATION_0) || (m_TileIndexT == TILE_STOP && m_TileFlagsT == ROTATION_0) || (m_TileIndexT == TILE_STOPS && (m_TileFlagsT == ROTATION_0 || m_TileFlagsT == ROTATION_180)) || (m_TileIndexT == TILE_STOPA) || (m_TileFIndex == TILE_STOP && m_TileFFlags == ROTATION_0) || (m_TileFIndexT == TILE_STOP && m_TileFFlagsT == ROTATION_0) || (m_TileFIndexT == TILE_STOPS && (m_TileFFlagsT == ROTATION_0 || m_TileFFlagsT == ROTATION_180)) || (m_TileFIndexT == TILE_STOPA) || (m_TileSIndex == TILE_STOP && m_TileSFlags == ROTATION_0) || (m_TileSIndexT == TILE_STOP && m_TileSFlagsT == ROTATION_0) || (m_TileSIndexT == TILE_STOPS && (m_TileSFlagsT == ROTATION_0 || m_TileSFlagsT == ROTATION_180)) || (m_TileSIndexT == TILE_STOPA)) && m_Core.m_Vel.y > 0)
2010-10-08 13:33:42 +00:00
{
2011-02-07 02:22:13 +00:00
//dbg_msg("","%f %f",GameServer()->Collision()->GetPos(MapIndex).y,m_Core.m_Pos.y);
if((int)GameServer()->Collision()->GetPos(MapIndexT).y)
if((int)GameServer()->Collision()->GetPos(MapIndexT).y < (int)m_Core.m_Pos.y)
m_Core.m_Pos = m_PrevPos;
2011-02-07 02:22:13 +00:00
m_Core.m_Vel.y = 0;
2010-10-08 13:33:42 +00:00
m_Core.m_Jumped = 0;
}
// handle switch tiles
2010-11-14 11:14:18 +00:00
if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_SWITCHOPEN && Team() != TEAM_SUPER)
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()->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()->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()->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)
{
Freeze(GameServer()->Collision()->GetSwitchDelay(MapIndex));
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_DFREEZE && Team() != TEAM_SUPER && 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 && 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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_START && m_Hit&DISABLE_HIT_RIFLE && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_RIFLE)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can shoot others with rifle");
m_Hit ^= DISABLE_HIT_RIFLE;
}
else if(GameServer()->Collision()->IsSwitch(MapIndex) == TILE_HIT_END && !(m_Hit&DISABLE_HIT_RIFLE) && GameServer()->Collision()->GetSwitchDelay(MapIndex) == WEAPON_RIFLE)
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"You can't shoot others with rifle");
m_Hit |= DISABLE_HIT_RIFLE;
}
2010-10-08 13:33:42 +00:00
int z = GameServer()->Collision()->IsTeleport(MapIndex);
if(z && Controller->m_TeleOuts[z-1].size())
2010-10-08 13:33:42 +00:00
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_Core.m_HookState = HOOK_RETRACTED;
int Num = Controller->m_TeleOuts[z-1].size();
m_Core.m_Pos = Controller->m_TeleOuts[z-1][(!Num)?Num:rand() % Num];
2010-10-08 13:33:42 +00:00
m_Core.m_HookPos = m_Core.m_Pos;
2010-10-10 23:46:13 +00:00
return;
2010-10-08 13:33:42 +00:00
}
int evilz = GameServer()->Collision()->IsEvilTeleport(MapIndex);
if(evilz && !m_Super && Controller->m_TeleOuts[evilz-1].size())
2010-10-08 13:33:42 +00:00
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_Core.m_HookState = HOOK_RETRACTED;
GameWorld()->ReleaseHooked(GetPlayer()->GetCID());
int Num = Controller->m_TeleOuts[evilz-1].size();
m_Core.m_Pos = Controller->m_TeleOuts[evilz-1][(!Num)?Num:rand() % Num];
2010-10-08 13:33:42 +00:00
m_Core.m_HookPos = m_Core.m_Pos;
m_Core.m_Vel = vec2(0,0);
2010-10-10 23:46:13 +00:00
return;
2010-10-08 13:33:42 +00:00
}
if(GameServer()->Collision()->IsCheckTeleport(MapIndex))
{
// 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())
{
m_Core.m_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_Core.m_HookState = HOOK_RETRACTED;
int Num = Controller->m_TeleCheckOuts[k].size();
m_Core.m_Pos = Controller->m_TeleCheckOuts[k][(!Num)?Num:rand() % Num];
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_HookedPlayer = -1;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
m_Core.m_HookState = HOOK_RETRACTED;
m_Core.m_Pos = SpawnPos;
m_Core.m_HookPos = m_Core.m_Pos;
}
return;
}
2010-10-08 13:33:42 +00:00
}
2011-01-29 00:59:50 +00:00
void CCharacter::DDRaceTick()
{
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
{
2011-01-29 00:59:50 +00:00
if (m_FreezeTime % Server()->TickSpeed() == 0 || m_FreezeTime == -1)
{
GameServer()->CreateDamageInd(m_Pos, 0, m_FreezeTime / 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
}
2011-01-29 00:59:50 +00:00
m_Core.m_Id = GetPlayer()->GetCID();
}
void CCharacter::DDRacePostCoreTick()
{
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())
{
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_pPlayer->m_DefEmoteReset = -1;
m_EmoteType = m_pPlayer->m_DefEmote = EMOTE_NORMAL;
m_EmoteStop = -1;
}
2011-07-22 12:29:27 +00:00
if (m_EndlessHook || (m_Super && g_Config.m_SvEndlessSuperHook))
m_Core.m_HookTick = 0;
if (m_DeepFreeze && !m_Super)
Freeze();
if (m_Super && m_Core.m_Jumped > 1)
m_Core.m_Jumped = 1;
int CurrentIndex = GameServer()->Collision()->GetMapIndex(m_Pos);
HandleSkippableTiles(CurrentIndex);
// handle Anti-Skip tiles
std::list < int > Indices = GameServer()->Collision()->GetMapIndices(m_PrevPos, m_Pos);
if(!Indices.empty())
for(std::list < int >::iterator i = Indices.begin(); i != Indices.end(); i++)
{
HandleTiles(*i);
//dbg_msg("Running","%d", *i);
}
else
{
HandleTiles(CurrentIndex);
//dbg_msg("Running","%d", CurrentIndex);
}
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)
{
for(int i = 0; i < NUM_WEAPONS; i++)
if(m_aWeapons[i].m_Got)
{
m_aWeapons[i].m_Ammo = 0;
}
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;
for(int i=0;i<NUM_WEAPONS;i++)
if(m_aWeapons[i].m_Got)
{
m_aWeapons[i].m_Ammo = -1;
}
if(!m_aWeapons[m_ActiveWeapon].m_Got)
m_ActiveWeapon = WEAPON_GUN;
m_FreezeTime = 0;
m_FreezeTick = 0;
2010-11-14 11:14:18 +00:00
if (m_ActiveWeapon==WEAPON_HAMMER) m_ReloadTimer = 0;
return true;
}
return false;
}
void CCharacter::GiveAllWeapons()
{
for(int i=1;i<NUM_WEAPONS-1;i++)
{
m_aWeapons[i].m_Got = true;
if(!m_FreezeTime) m_aWeapons[i].m_Ammo = -1;
}
return;
}
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);
}
else
{
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_LastBroadcast = 0;
m_TeamBeforeSuper = 0;
m_Core.m_Id = GetPlayer()->GetCID();
if(GetPlayer()->m_IsUsingDDRaceClient) ((CGameControllerDDRace*)GameServer()->m_pController)->m_Teams.SendTeamsState(GetPlayer()->GetCID());
2011-02-14 21:34:46 +00:00
if(g_Config.m_SvTeam == 2)
2011-01-29 14:31:50 +00:00
{
GameServer()->SendChatTarget(GetPlayer()->GetCID(),"Please join a team before you start");
m_LastStartWarning = Server()->Tick();
}
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_RIFLE|DISABLE_HIT_SHOTGUN;
Teams()->m_Core.SetSolo(m_pPlayer->GetCID(), false);
}