Guest User

Untitled

a guest
Apr 20th, 2018
88
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 44.49 KB | None | 0 0
  1. /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
  2. /* If you are missing that file, acquire a complete release at teeworlds.com.                */
  3. #include <new>
  4. #include <engine/shared/config.h>
  5. #include <game/server/gamecontext.h>
  6. #include <game/mapitems.h>
  7.  
  8. #include "../gamemodes/zesc.h"
  9.  
  10. #include "character.h"
  11. #include "laser.h"
  12. #include "projectile.h"
  13. #include "door.h"
  14. #include "wall.h"
  15.  
  16. //input count
  17. struct CInputCount
  18. {
  19.     int m_Presses;
  20.     int m_Releases;
  21. };
  22.  
  23. CInputCount CountInput(int Prev, int Cur)
  24. {
  25.     CInputCount c = {0, 0};
  26.     Prev &= INPUT_STATE_MASK;
  27.     Cur &= INPUT_STATE_MASK;
  28.     int i = Prev;
  29.  
  30.     while(i != Cur)
  31.     {
  32.         i = (i+1)&INPUT_STATE_MASK;
  33.         if(i&1)
  34.             c.m_Presses++;
  35.         else
  36.             c.m_Releases++;
  37.     }
  38.  
  39.     return c;
  40. }
  41.  
  42.  
  43. MACRO_ALLOC_POOL_ID_IMPL(CCharacter, MAX_CLIENTS)
  44.  
  45. // Character, "physical" player's part
  46. CCharacter::CCharacter(CGameWorld *pWorld)
  47. : CEntity(pWorld, CGameWorld::ENTTYPE_CHARACTER)
  48. {
  49.     m_ProximityRadius = ms_PhysSize;
  50.     m_Health = 0;
  51.     m_Armor = 0;
  52. }
  53.  
  54. void CCharacter::Reset()
  55. {
  56.     Destroy();
  57. }
  58.  
  59. bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
  60. {
  61.     m_EmoteStop = -1;
  62.     m_LastAction = -1;
  63.     m_ActiveWeapon = WEAPON_GUN;
  64.     if(pPlayer->GetTeam() == TEAM_RED)
  65.         m_ActiveWeapon = WEAPON_HAMMER;
  66.     m_LastWeapon = WEAPON_HAMMER;
  67.     m_QueuedWeapon = -1;
  68.  
  69.     m_pPlayer = pPlayer;
  70.     m_Pos = Pos;
  71.  
  72.     m_Core.Reset();
  73.     m_Core.Init(&GameServer()->m_World.m_Core, GameServer()->Collision());
  74.     m_Core.m_Pos = m_Pos;
  75.     GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = &m_Core;
  76.  
  77.     m_ReckoningTick = 0;
  78.     mem_zero(&m_SendCore, sizeof(m_SendCore));
  79.     mem_zero(&m_ReckoningCore, sizeof(m_ReckoningCore));
  80.  
  81.     GameServer()->m_World.InsertEntity(this);
  82.     m_Alive = true;
  83.  
  84.     m_LastSpeedup = -1;
  85.  
  86.     GameServer()->m_pController->OnCharacterSpawn(this);
  87.     int H;
  88.     H = 60+GetPlayer()->m_Lvl;
  89.     m_Health = H;
  90.     m_Armor = H;
  91.     return true;
  92. }
  93.  
  94. void CCharacter::Destroy()
  95. {
  96.     GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
  97.     m_Alive = false;
  98. }
  99.  
  100. void CCharacter::SetWeapon(int W)
  101. {
  102.     if(W == m_ActiveWeapon || m_pPlayer->GetTeam() == TEAM_RED)
  103.         return;
  104.  
  105.     m_LastWeapon = m_ActiveWeapon;
  106.     m_QueuedWeapon = -1;
  107.     m_ActiveWeapon = W;
  108.     GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH);
  109.  
  110.     if(m_ActiveWeapon < 0 || m_ActiveWeapon >= NUM_WEAPONS)
  111.         m_ActiveWeapon = 0;
  112. }
  113.  
  114. bool CCharacter::IsGrounded()
  115. {
  116.     if(GameServer()->Collision()->CheckPoint(m_Pos.x+m_ProximityRadius/2, m_Pos.y+m_ProximityRadius/2+5))
  117.         return true;
  118.     if(GameServer()->Collision()->CheckPoint(m_Pos.x-m_ProximityRadius/2, m_Pos.y+m_ProximityRadius/2+5))
  119.         return true;
  120.     return false;
  121. }
  122.  
  123.  
  124. void CCharacter::HandleNinja()
  125. {
  126.     if(m_ActiveWeapon != WEAPON_NINJA)
  127.         return;
  128.  
  129.     if ((Server()->Tick() - m_Ninja.m_ActivationTick) > (g_pData->m_Weapons.m_Ninja.m_Duration * Server()->TickSpeed() / 1000))
  130.     {
  131.         // time's up, return
  132.         m_aWeapons[WEAPON_NINJA].m_Got = false;
  133.         m_ActiveWeapon = m_LastWeapon;
  134.  
  135.         SetWeapon(m_ActiveWeapon);
  136.         return;
  137.     }
  138.  
  139.     // force ninja Weapon
  140.     SetWeapon(WEAPON_NINJA);
  141.  
  142.     m_Ninja.m_CurrentMoveTime--;
  143.  
  144.     if (m_Ninja.m_CurrentMoveTime == 0)
  145.     {
  146.         // reset velocity
  147.         m_Core.m_Vel = m_Ninja.m_ActivationDir*m_Ninja.m_OldVelAmount;
  148.     }
  149.  
  150.     if (m_Ninja.m_CurrentMoveTime > 0)
  151.     {
  152.         // Set velocity
  153.         m_Core.m_Vel = m_Ninja.m_ActivationDir * g_pData->m_Weapons.m_Ninja.m_Velocity;
  154.         vec2 OldPos = m_Pos;
  155.         GameServer()->Collision()->MoveBox(&m_Core.m_Pos, &m_Core.m_Vel, vec2(m_ProximityRadius, m_ProximityRadius), 0.f);
  156.  
  157.         // reset velocity so the client doesn't predict stuff
  158.         m_Core.m_Vel = vec2(0.f, 0.f);
  159.  
  160.         // check if we Hit anything along the way
  161.         {
  162.             CCharacter *aEnts[MAX_CLIENTS];
  163.             vec2 Dir = m_Pos - OldPos;
  164.             float Radius = m_ProximityRadius * 2.0f;
  165.             vec2 Center = OldPos + Dir * 0.5f;
  166.             int Num = GameServer()->m_World.FindEntities(Center, Radius, (CEntity**)aEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
  167.  
  168.             for (int i = 0; i < Num; ++i)
  169.             {
  170.                 if (aEnts[i] == this)
  171.                     continue;
  172.  
  173.                 // make sure we haven't Hit this object before
  174.                 bool bAlreadyHit = false;
  175.                 for (int j = 0; j < m_NumObjectsHit; j++)
  176.                 {
  177.                     if (m_apHitObjects[j] == aEnts[i])
  178.                         bAlreadyHit = true;
  179.                 }
  180.                 if (bAlreadyHit)
  181.                     continue;
  182.  
  183.                 // check so we are sufficiently close
  184.                 if (distance(aEnts[i]->m_Pos, m_Pos) > (m_ProximityRadius * 2.0f))
  185.                     continue;
  186.  
  187.                 // Hit a player, give him damage and stuffs...
  188.                 GameServer()->CreateSound(aEnts[i]->m_Pos, SOUND_NINJA_HIT);
  189.                 // set his velocity to fast upward (for now)
  190.                 if(m_NumObjectsHit < 10)
  191.                     m_apHitObjects[m_NumObjectsHit++] = aEnts[i];
  192.  
  193.                 aEnts[i]->TakeDamage(vec2(0, -10.0f), g_pData->m_Weapons.m_Ninja.m_pBase->m_Damage, m_pPlayer->GetCID(), WEAPON_NINJA);
  194.             }
  195.         }
  196.  
  197.         return;
  198.     }
  199.  
  200.     return;
  201. }
  202.  
  203.  
  204. void CCharacter::DoWeaponSwitch()
  205. {
  206.     // make sure we can switch
  207.     if(m_ReloadTimer != 0 || m_QueuedWeapon == -1 || m_aWeapons[WEAPON_NINJA].m_Got)
  208.         return;
  209.  
  210.     // switch Weapon
  211.     SetWeapon(m_QueuedWeapon);
  212. }
  213.  
  214. void CCharacter::HandleWeaponSwitch()
  215. {
  216.     int WantedWeapon = m_ActiveWeapon;
  217.     if(m_QueuedWeapon != -1)
  218.         WantedWeapon = m_QueuedWeapon;
  219.  
  220.     // select Weapon
  221.     int Next = CountInput(m_LatestPrevInput.m_NextWeapon, m_LatestInput.m_NextWeapon).m_Presses;
  222.     int Prev = CountInput(m_LatestPrevInput.m_PrevWeapon, m_LatestInput.m_PrevWeapon).m_Presses;
  223.  
  224.     if(Next < 128) // make sure we only try sane stuff
  225.     {
  226.         while(Next) // Next Weapon selection
  227.         {
  228.             WantedWeapon = (WantedWeapon+1)%NUM_WEAPONS;
  229.             if(m_aWeapons[WantedWeapon].m_Got)
  230.                 Next--;
  231.         }
  232.     }
  233.  
  234.     if(Prev < 128) // make sure we only try sane stuff
  235.     {
  236.         while(Prev) // Prev Weapon selection
  237.         {
  238.             WantedWeapon = (WantedWeapon-1)<0?NUM_WEAPONS-1:WantedWeapon-1;
  239.             if(m_aWeapons[WantedWeapon].m_Got)
  240.                 Prev--;
  241.         }
  242.     }
  243.  
  244.     // Direct Weapon selection
  245.     if(m_LatestInput.m_WantedWeapon)
  246.         WantedWeapon = m_Input.m_WantedWeapon-1;
  247.  
  248.     // check for insane values
  249.     if(WantedWeapon >= 0 && WantedWeapon < NUM_WEAPONS && WantedWeapon != m_ActiveWeapon && m_aWeapons[WantedWeapon].m_Got)
  250.         m_QueuedWeapon = WantedWeapon;
  251.  
  252.     DoWeaponSwitch();
  253. }
  254.  
  255. void CCharacter::FireWeapon()
  256. {
  257.     if(m_ReloadTimer != 0)
  258.         return;
  259.  
  260.     DoWeaponSwitch();
  261.     vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY));
  262.  
  263.     bool FullAuto = false;
  264.     if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE)
  265.         FullAuto = true;
  266.     if(Server()->IsAuthed(m_pPlayer->GetCID()))
  267.         FullAuto = true;
  268.     if(Spree >= 5)
  269.         FullAuto = true;
  270.     if (GetPlayer()->GetTeam() == TEAM_RED && GetPlayer()->m_Lvl > 15 && m_ActiveWeapon == WEAPON_HAMMER)
  271.         FullAuto = true;
  272.     if (GetPlayer()->GetTeam() == TEAM_BLUE && GetPlayer()->m_Lvl > 70 && m_ActiveWeapon == WEAPON_GUN)
  273.         FullAuto = true;
  274.  
  275.     // check if we gonna fire
  276.     bool WillFire = false;
  277.     if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses)
  278.         WillFire = true;
  279.  
  280.     if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo)
  281.         WillFire = true;
  282.  
  283.     if(!WillFire)
  284.         return;
  285.  
  286.     // check for ammo
  287.     if(!m_aWeapons[m_ActiveWeapon].m_Ammo)
  288.     {
  289.         // 125ms is a magical limit of how fast a human can click
  290.         m_ReloadTimer = 125 * Server()->TickSpeed() / 1000;
  291.         GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO);
  292.         return;
  293.     }
  294.  
  295.     vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f;
  296.  
  297.     switch(m_ActiveWeapon)
  298.     {
  299. case WEAPON_HAMMER:
  300.         {
  301.             // reset objects Hit
  302.             m_NumObjectsHit = 0;
  303.             GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE);
  304.             CCharacter *apEnts[MAX_CLIENTS];
  305.             int Hits = 0;
  306.             if(m_pPlayer->GetTeam() == TEAM_RED)
  307.             {
  308.                 int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts,
  309.                     MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
  310.  
  311.                 for (int i = 0; i < Num; ++i)
  312.                 {
  313.                     CCharacter *pTarget = apEnts[i];
  314.  
  315.                     if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL) || pTarget->m_pPlayer->GetTeam() == TEAM_RED)
  316.                         continue;
  317.  
  318.                     // set his velocity to fast upward (for now)
  319.                     if(length(pTarget->m_Pos-ProjStartPos) > 0.0f)
  320.                         GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*1.5f);
  321.                     else
  322.                         GameServer()->CreateHammerHit(ProjStartPos);
  323.  
  324.                     GameServer()->m_apPlayers[pTarget->m_pPlayer->GetCID()]->SetZomb(m_pPlayer->GetCID());
  325.  
  326.                     // a nice sound
  327.                     GameServer()->CreateSound(pTarget->m_Pos, SOUND_PLAYER_PAIN_LONG);
  328.  
  329.                     Hits++;
  330.                 }
  331.             }
  332.             else if((m_Item == HITEM_HAMMER) && m_Armor)
  333.             {
  334.                 CDoor *pDoor = new CDoor(&GameServer()->m_World, -1, g_Config.m_SvHdoorReopenTime);
  335.                 pDoor->m_Pos = m_Pos;
  336.                 m_Armor--;
  337.             }
  338.             else
  339.             {
  340.                 int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts,
  341.                     MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
  342.  
  343.                 for (int i = 0; i < Num; ++i)
  344.                 {
  345.                     CCharacter *pTarget = apEnts[i];
  346.  
  347.                     if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL))
  348.                         continue;
  349.  
  350.                     // set his velocity to fast upward (for now)
  351.                     if(length(pTarget->m_Pos-ProjStartPos) > 0.0f)
  352.                     {
  353.                         if (GetPlayer()->m_Lvl < 50)
  354.                             GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*0.5f);
  355.                         else if (GetPlayer()->m_Lvl < 100 && GetPlayer()->m_Lvl > 50)
  356.                             GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*1.0f);
  357.                         else if (GetPlayer()->m_Lvl > 100)
  358.                             GameServer()->CreateHammerHit(pTarget->m_Pos-normalize(pTarget->m_Pos-ProjStartPos)*m_ProximityRadius*1.5f);
  359.                     }
  360.                     else
  361.                         GameServer()->CreateHammerHit(ProjStartPos);
  362.  
  363.                     vec2 Dir;
  364.                     if (length(pTarget->m_Pos - m_Pos) > 0.0f)
  365.                         Dir = normalize(pTarget->m_Pos - m_Pos);
  366.                     else
  367.                         Dir = vec2(0.f, -1.f);
  368.  
  369.                     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,
  370.                         m_pPlayer->GetCID(), m_ActiveWeapon);
  371.                     Hits++;
  372.                 }
  373.             }
  374.  
  375.             // if we Hit anything, we have to wait for the reload
  376.             if(Hits)
  377.                 m_ReloadTimer = Server()->TickSpeed()/3;
  378.                
  379.             if (GetPlayer()->m_HealthHammer)
  380.             {
  381.                 CDoor *pDoor = new CDoor(&GameServer()->m_World, -1, g_Config.m_SvHdoorReopenTime);
  382.                 pDoor->m_Pos = m_Pos;
  383.             }
  384.  
  385.         } break;
  386.  
  387.         case WEAPON_GUN:
  388.         {
  389.             if (GetPlayer()->m_Lvl > 150)
  390.             {
  391.                     int ShotSpread;
  392.                     int Z;
  393.                     Z = 1;
  394.                 for(int i = 0; i <= 1; ++i)
  395.                 {
  396.  
  397.                     float Spreading[] = {-0.070f, 0, 0.070f, 0.185f};//Z = 2;
  398.                     float a = GetAngle(Direction);
  399.                     a += Spreading[i+Z];
  400.                     float v = 1-(absolute(i)/(float)ShotSpread);
  401.                     float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
  402.                     CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GUN,
  403.                     m_pPlayer->GetCID(),
  404.                     ProjStartPos,
  405.                     vec2(cosf(a), sinf(a))*Speed,
  406.                     (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
  407.                     1, 0, 15, -1, WEAPON_GUN);
  408.                 }
  409.             }
  410.             else
  411.             {
  412.                 CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GUN,
  413.                 m_pPlayer->GetCID(),
  414.                 ProjStartPos,
  415.                 Direction,
  416.                 (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
  417.                 1, false, 15, -1, WEAPON_GUN);
  418.             }
  419.  
  420.             GameServer()->CreateSound(m_Pos, SOUND_GUN_FIRE);
  421.        
  422.         } break;
  423.  
  424.         case WEAPON_SHOTGUN:
  425.         {
  426.             int ShotSpread;
  427.             int Z;
  428.             if (GetPlayer()->m_Lvl < 40)
  429.                 Z = 2;
  430.             else if (GetPlayer()->m_Lvl >= 40 && GetPlayer()->m_Lvl < 90)          
  431.                 Z = 4;
  432.             else if (GetPlayer()->m_Lvl > 90 && GetPlayer()->m_Lvl < 120)
  433.                 Z = 6;
  434.             else if (GetPlayer()->m_Lvl >= 120 && GetPlayer()->m_Lvl <= 200)
  435.                 Z = 10;
  436.             else Z = 12;
  437.             ShotSpread = Z;
  438.             CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE);
  439.             Msg.AddInt(ShotSpread*2+1);
  440.             int Force = GetPlayer()->m_Lvl;
  441.             if (Force < 10)
  442.                 Force = 10;
  443.             if (Force > 20)
  444.                 Force = 22;
  445.  
  446.             for(int i = -ShotSpread; i <= ShotSpread; ++i)
  447.             {
  448. //              float Spreading[];// = {-0.185f, -0.070f, 0, 0.070f, 0.185f};
  449.                 if (GetPlayer()->m_Lvl < 40)
  450.                 {
  451.                     float Spreading[] = {-0.185f, -0.070f, 0, 0.070f, 0.185f};//Z = 2;
  452.                     float a = GetAngle(Direction);
  453.                     a += Spreading[i+Z];
  454.                     float v = 1-(absolute(i)/(float)ShotSpread);
  455.                     float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
  456.                     CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
  457.                     m_pPlayer->GetCID(),
  458.                     ProjStartPos,
  459.                     vec2(cosf(a), sinf(a))*Speed,
  460.                     (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
  461.                     1, 0, Force, -1, WEAPON_SHOTGUN);
  462.                 }
  463.                 else if (GetPlayer()->m_Lvl >= 40 && GetPlayer()->m_Lvl < 90)      
  464.                 {
  465.                     float Spreading[] = {-0.280f, -0.210f, -0.140f, -0.070f, 0, 0.070f, 0.140f, 0.210f, 0.280f};//Z = 4;
  466.                     float a = GetAngle(Direction);
  467.                     a += Spreading[i+Z];
  468.                     float v = 1-(absolute(i)/(float)ShotSpread);
  469.                     float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
  470.                     CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
  471.                     m_pPlayer->GetCID(),
  472.                     ProjStartPos,
  473.                     vec2(cosf(a), sinf(a))*Speed,
  474.                     (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
  475.                     1, 0, Force, -1, WEAPON_SHOTGUN);
  476.                 }
  477.                 else if (GetPlayer()->m_Lvl > 90 && GetPlayer()->m_Lvl < 120)
  478.                 {
  479.                     float Spreading[] = {-0.420f, -0.350f, -0.280f, -0.210f, -0.140f, -0.070f, 0, 0.070f, 0.140f, 0.210f, 0.280f, 0.350f, 0.420f};//z = 6;
  480.                     float a = GetAngle(Direction);
  481.                     a += Spreading[i+Z];
  482.                     float v = 1-(absolute(i)/(float)ShotSpread);
  483.                     float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
  484.                     CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
  485.                     m_pPlayer->GetCID(),
  486.                     ProjStartPos,
  487.                     vec2(cosf(a), sinf(a))*Speed,
  488.                     (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
  489.                     1, 0, Force, -1, WEAPON_SHOTGUN);
  490.                 }
  491.                 else if (GetPlayer()->m_Lvl >= 120 && GetPlayer()->m_Lvl <= 200)
  492.                 {
  493.                     float Spreading[] = {-0.700f, -0.630f, -0.560f, -0.490f, -0.420f, -0.350f, -0.280f, -0.210f, -0.140f, -0.070f, 0, 0.070f, 0.140f, 0.210f, 0.280f, 0.350f, 0.420f, 0.490f, 0.560f, 0.630f, 0.700f}; // разница в 70
  494.                     float a = GetAngle(Direction);
  495.                     a += Spreading[i+Z];
  496.                     float v = 1-(absolute(i)/(float)ShotSpread);
  497.                     float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
  498.                     CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
  499.                     m_pPlayer->GetCID(),
  500.                     ProjStartPos,
  501.                     vec2(cosf(a), sinf(a))*Speed,
  502.                     (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
  503.                     1, 0, Force, -1, WEAPON_SHOTGUN);
  504.                 }
  505.                 else
  506.                 {
  507.                     float Spreading[] = {-0.840f, -0.770f, -0.700f, -0.630f, -0.560f, -0.490f, -0.420f, -0.350f, -0.280f, -0.210f, -0.140f, -0.070f, 0, 0.070f, 0.140f, 0.210f, 0.280f, 0.350f, 0.420f, 0.490f, 0.560f, 0.630f, 0.700f, 0.770f, 0.840f }; // разница в 70
  508.                     float a = GetAngle(Direction);
  509.                     a += Spreading[i+Z];
  510.                     float v = 1-(absolute(i)/(float)ShotSpread);
  511.                     float Speed = mix((float)GameServer()->Tuning()->m_ShotgunSpeeddiff, 1.0f, v);
  512.                     CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN,
  513.                     m_pPlayer->GetCID(),
  514.                     ProjStartPos,
  515.                     vec2(cosf(a), sinf(a))*Speed,
  516.                     (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime),
  517.                     1, 0, Force, -1, WEAPON_SHOTGUN);
  518.                 }
  519.                
  520.             }
  521.             GameServer()->CreateSound(m_Pos, SOUND_SHOTGUN_FIRE);
  522.            
  523.         } break;
  524.  
  525.         case WEAPON_GRENADE:
  526.         {
  527.             if (m_Grenades > g_Config.m_SvMaxGrenades)
  528.             {
  529.                 GameServer()->SendChatTarget(GetPlayer()->GetCID(), "Your greandes is to much");
  530.                 return;
  531.             }
  532.             else
  533.             {
  534.             if (GameServer()->Server()->IsAuthed(GetPlayer()->GetCID()))
  535.             CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GRENADE,
  536.                 m_pPlayer->GetCID(),
  537.                 ProjStartPos,
  538.                 Direction,
  539.                 99999999999,
  540.                 20, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);
  541.             else if (GameServer()->Server()->IsAuthed(GetPlayer()->GetCID()) && GetPlayer()->m_Lvl > 40)
  542.             {
  543.                 for (int i=0; i < 5; ++i)
  544.                 CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GRENADE,
  545.                 m_pPlayer->GetCID(),
  546.                 ProjStartPos,
  547.                 Direction,
  548.                 99999999999,
  549.                 20, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);
  550.             }
  551.             else
  552.             CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GRENADE,
  553.                 m_pPlayer->GetCID(),
  554.                 ProjStartPos,
  555.                 Direction,
  556.                 99999999999,
  557.                 5, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE);
  558.  
  559.             if (!GetPlayer()->m_MiniXXl)
  560.                 GameServer()->CreateSound(m_Pos, SOUND_GRENADE_FIRE);
  561.             }
  562.         } break;
  563.  
  564.         case WEAPON_RIFLE:
  565.         {  
  566.             if (GetPlayer()->GetTeam() == TEAM_BLUE)
  567.             {
  568.             //int B = g_Config.m_SvRifleTime + 500;
  569.             //new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID(), B);
  570.             int D;
  571.             // if (GetPlayer()->m_Lvl < 40)
  572.                 D = 1;
  573.             /* else if (GetPlayer()->m_Lvl > 40 && GetPlayer()->m_Lvl < 60)
  574.                 D = 2;
  575.             else if (GetPlayer()->m_Lvl > 60 && GetPlayer()->m_Lvl < 80)
  576.                 D = 3;
  577.             else if (GetPlayer()->m_Lvl > 80 && GetPlayer()->m_Lvl < 100)
  578.                 D = 4;
  579.             else if (GetPlayer()->m_Lvl > 100)
  580.                 D = 5; */
  581.             vec2 To;
  582.             if (!(m_HammerPos == vec2(0,0)))
  583.             {
  584.                 if (m_HammerPos == m_Pos)
  585.                 {
  586.                     GameServer()->SendChatTarget(m_pPlayer->GetCID(), "You cant make a wall here :P");
  587.                     m_HammerPos = vec2(0,0);
  588.                     m_aWeapons[WEAPON_RIFLE].m_Ammo = 2;
  589.                     return;
  590.                 }
  591.                
  592.  
  593.                     new CWall(GameWorld(), m_HammerPos, m_Pos, m_pPlayer->GetCID(), g_Config.m_SvRifleTime, false, D);
  594.                
  595.                 //m_HammerPos = vec2(0,0);
  596.             }
  597.             else
  598.              m_HammerPos = m_Pos;
  599.             //vec2 To = m_Pos + Direction * g_Config.m_SvWallLength;
  600.             //new CWall(GameWorld(), To, m_Pos, m_pPlayer->GetCID(), g_Config.m_SvRifleTime);
  601.             }
  602.             else if (GetPlayer()->m_Lvl > 49)
  603.             {
  604.                 new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID());
  605.             }
  606.             GameServer()->CreateSound(m_Pos, SOUND_RIFLE_FIRE);
  607.         } break;
  608.  
  609.         case WEAPON_NINJA:
  610.         {
  611.             // reset Hit objects
  612.             m_NumObjectsHit = 0;
  613.  
  614.             m_Ninja.m_ActivationDir = Direction;
  615.             m_Ninja.m_CurrentMoveTime = g_pData->m_Weapons.m_Ninja.m_Movetime * Server()->TickSpeed() / 1000;
  616.             m_Ninja.m_OldVelAmount = length(m_Core.m_Vel);
  617.  
  618.             GameServer()->CreateSound(m_Pos, SOUND_NINJA_FIRE);
  619.         } break;
  620.  
  621.     }
  622.  
  623.     m_AttackTick = Server()->Tick();
  624.     int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime;
  625.     if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0 && !g_Config.m_SvInfiniteAmmo) // -1 == unlimited
  626.         m_aWeapons[m_ActiveWeapon].m_Ammo--;
  627.  
  628.  
  629.        
  630.     if(Spree > 10)
  631.         {
  632.             if(!m_ReloadTimer)
  633.                 m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 2300;
  634.         }
  635.        
  636.     if(!m_ReloadTimer)
  637.         m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / (1000+(GetPlayer()->m_Lvl*4));
  638.            
  639.        
  640. }
  641.  
  642. void CCharacter::HandleWeapons()
  643. {
  644.     //ninja
  645.     HandleNinja();
  646.  
  647.     // check reload timer
  648.     if(m_ReloadTimer)
  649.     {  
  650.        /* if (GameServer()->Server()->IsAuthed(GetPlayer()->GetCID()))
  651.         {
  652.             m_ReloadTimer = m_ReloadTimer * Server()->TickSpeed() / 1000;
  653.             m_ReloadTimer--;
  654.             return;
  655.         }
  656.         else */
  657.         m_ReloadTimer--;
  658.         return;
  659.     }
  660.  
  661.     // fire Weapon, if wanted
  662.     FireWeapon();
  663.  
  664.     // ammo regen
  665.     int AmmoRegenTime = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Ammoregentime;
  666.     if(Server()->IsAuthed(m_pPlayer->GetCID()))
  667.         AmmoRegenTime = AmmoRegenTime / 50;
  668.     if(Spree >= 5)
  669.         AmmoRegenTime = AmmoRegenTime / 50;
  670.     if(m_Item == HITEM_GUN)
  671.         AmmoRegenTime = AmmoRegenTime / 3;
  672.     if(AmmoRegenTime)
  673.     {
  674.         // If equipped and not active, regen ammo?
  675.         if (m_ReloadTimer <= 0)
  676.         {
  677.             if (m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart < 0)
  678.                 m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = Server()->Tick();
  679.  
  680.             if ((Server()->Tick() - m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart) >= AmmoRegenTime * Server()->TickSpeed() / 1000)
  681.             {
  682.                 // Add some ammo
  683.                 m_aWeapons[m_ActiveWeapon].m_Ammo = min(m_aWeapons[m_ActiveWeapon].m_Ammo + 1, 10);
  684.                 m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1;
  685.             }
  686.         }
  687.         else
  688.         {
  689.             m_aWeapons[m_ActiveWeapon].m_AmmoRegenStart = -1;
  690.         }
  691.     }
  692.  
  693.     return;
  694. }
  695.  
  696. bool CCharacter::GiveWeapon(int Weapon, int Ammo)
  697. {
  698.     if(m_aWeapons[Weapon].m_Ammo < g_pData->m_Weapons.m_aId[Weapon].m_Maxammo || !m_aWeapons[Weapon].m_Got)
  699.     {
  700.         m_aWeapons[Weapon].m_Got = true;
  701.         if (GetPlayer()->m_Lvl < 50)
  702.         {
  703.             if (Weapon == WEAPON_SHOTGUN)
  704.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, 10);
  705.             if (Weapon == WEAPON_GRENADE)
  706.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, 10);
  707.             if (Weapon == WEAPON_RIFLE)
  708.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, 2);
  709.             if (Weapon == WEAPON_HAMMER)
  710.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, Ammo);
  711.         }
  712.         else if (GetPlayer()->m_Lvl > 50 && GetPlayer()->m_Lvl < 100)
  713.         {
  714.             if (Weapon == WEAPON_SHOTGUN)
  715.                 m_aWeapons[Weapon].m_Ammo = min(20, 20);
  716.             if (Weapon == WEAPON_GRENADE)
  717.                 m_aWeapons[Weapon].m_Ammo = min(20, 20);
  718.             if (Weapon == WEAPON_RIFLE)
  719.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, 2);
  720.             if (Weapon == WEAPON_HAMMER)
  721.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, Ammo);
  722.         }
  723.         else if (GetPlayer()->m_Lvl > 100)
  724.         {
  725.             if (Weapon == WEAPON_SHOTGUN)
  726.                 m_aWeapons[Weapon].m_Ammo = min(30, 30);
  727.             if (Weapon == WEAPON_GRENADE)
  728.                 m_aWeapons[Weapon].m_Ammo = min(30, 30);    
  729.             if (Weapon == WEAPON_RIFLE)
  730.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, 4);
  731.             if (Weapon == WEAPON_HAMMER)
  732.                 m_aWeapons[Weapon].m_Ammo = min(g_pData->m_Weapons.m_aId[Weapon].m_Maxammo, Ammo); 
  733.         }
  734.         return true;
  735.     }
  736.     return false;
  737. }
  738.  
  739. void CCharacter::GiveNinja()
  740. {
  741.     m_Ninja.m_ActivationTick = Server()->Tick();
  742.     m_aWeapons[WEAPON_NINJA].m_Got = true;
  743.     m_aWeapons[WEAPON_NINJA].m_Ammo = -1;
  744.     if (m_ActiveWeapon != WEAPON_NINJA)
  745.         m_LastWeapon = m_ActiveWeapon;
  746.     m_ActiveWeapon = WEAPON_NINJA;
  747.  
  748.     GameServer()->CreateSound(m_Pos, SOUND_PICKUP_NINJA);
  749. }
  750.  
  751. void CCharacter::SetEmote(int Emote, int Tick)
  752. {
  753.     m_EmoteType = Emote;
  754.     m_EmoteStop = Tick;
  755. }
  756.  
  757. void CCharacter::OnPredictedInput(CNetObj_PlayerInput *pNewInput)
  758. {
  759.     // check for changes
  760.     if(mem_comp(&m_Input, pNewInput, sizeof(CNetObj_PlayerInput)) != 0)
  761.         m_LastAction = Server()->Tick();
  762.  
  763.     // copy new input
  764.     mem_copy(&m_Input, pNewInput, sizeof(m_Input));
  765.     m_NumInputs++;
  766.  
  767.     // or are not allowed to aim in the center
  768.     if(m_Input.m_TargetX == 0 && m_Input.m_TargetY == 0)
  769.         m_Input.m_TargetY = -1;
  770. }
  771.  
  772. void CCharacter::OnDirectInput(CNetObj_PlayerInput *pNewInput)
  773. {
  774.     mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput));
  775.     mem_copy(&m_LatestInput, pNewInput, sizeof(m_LatestInput));
  776.  
  777.     if(m_NumInputs > 2 && m_pPlayer->GetTeam() != TEAM_SPECTATORS)
  778.     {
  779.         HandleWeaponSwitch();
  780.         FireWeapon();
  781.     }
  782.  
  783.     mem_copy(&m_LatestPrevInput, &m_LatestInput, sizeof(m_LatestInput));
  784. }
  785.  
  786. void CCharacter::ResetInput()
  787. {
  788.     m_Input.m_Direction = 0;
  789.     m_Input.m_Hook = 0;
  790.     // simulate releasing the fire button
  791.     if((m_Input.m_Fire&1) != 0)
  792.         m_Input.m_Fire++;
  793.     m_Input.m_Fire &= INPUT_STATE_MASK;
  794.     m_Input.m_Jump = 0;
  795.     m_LatestPrevInput = m_LatestInput = m_Input;
  796. }
  797.  
  798. void CCharacter::Tick()
  799. {
  800.     if(m_pPlayer->m_ForceBalanced)
  801.     {
  802.         char Buf[128];
  803.         str_format(Buf, sizeof(Buf), "You were moved to %s due to team balancing", GameServer()->m_pController->GetTeamName(m_pPlayer->GetTeam()));
  804.         GameServer()->SendBroadcast(Buf, m_pPlayer->GetCID());
  805.  
  806.         m_pPlayer->m_ForceBalanced = false;
  807.     }
  808.  
  809.     // save jumping state
  810.     int Jumped = m_Core.m_Jumped;
  811.  
  812.     m_Core.m_Input = m_Input;
  813.     m_Core.Tick(true);
  814.  
  815.     CGameControllerZESC *pzESC = GameServer()->zESCController();
  816.  
  817.     /* if(g_Config.m_SvRegen > 0 && (Server()->Tick()%g_Config.m_SvRegen) == 0)
  818.     {
  819.         if(m_Health < 10)
  820.             m_Health++;
  821.         else if(m_Armor < 10)
  822.             m_Armor++;
  823.     } */
  824.  
  825.     // tile index
  826.     int TileIndex = GameServer()->Collision()->GetIndex(m_PrevPos, m_Pos);
  827.  
  828.     int z = GameServer()->Collision()->IsHoldpoint(m_Pos);
  829.     int ct = -1;
  830.     if(z != -1 && m_Alive)
  831.         pzESC->OnHoldpoint(z);
  832.  
  833.     z = GameServer()->Collision()->IsZStop(m_Pos);
  834.     if(z != -1 && m_pPlayer && m_pPlayer->GetTeam() == TEAM_BLUE && m_Alive)
  835.         pzESC->OnZStop(z);
  836.  
  837.     z = GameServer()->Collision()->IsTrigger(m_Pos, m_pPlayer->GetTeam());
  838.     if(z != -1 && m_Alive)
  839.         GameServer()->m_pController->OnTrigger(z);
  840.  
  841.     z = GameServer()->Collision()->IsCustomTeleport(m_Pos);
  842.     if(z != -1 && m_Alive)
  843.         ct = GameServer()->m_pController->OnCustomTeleporter(z, m_pPlayer->GetTeam());
  844.     if(ct != -1)
  845.     {
  846.         // check double jump
  847.         if(Jumped&3 && m_Core.m_Jumped != Jumped)
  848.             m_Core.m_Jumped = Jumped;
  849.  
  850.         m_Core.m_HookedPlayer = -1;
  851.         m_Core.m_HookState = HOOK_RETRACTED;
  852.         m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
  853.         m_Core.m_HookState = HOOK_RETRACTED;
  854.         m_Core.m_Pos = pzESC->m_pTeleporter[ct];
  855.         m_Core.m_HookPos = m_Core.m_Pos;
  856.         //Resetting velocity to prevent exploit
  857.         if(g_Config.m_SvTeleportVelReset)
  858.             m_Core.m_Vel = vec2(0,0);
  859.         if(g_Config.m_SvStrip)
  860.         {
  861.             m_ActiveWeapon = WEAPON_GUN;
  862.             m_LastWeapon = WEAPON_HAMMER;
  863.             m_aWeapons[WEAPON_HAMMER].m_Got = true;
  864.             m_aWeapons[WEAPON_GUN].m_Got = true;
  865.             for(int i = 2; i < NUM_WEAPONS; i++)
  866.                 m_aWeapons[i].m_Got = false;
  867.         }
  868.     }
  869.     if(GameServer()->Collision()->IsWeaponStrip(m_Pos))
  870.     {
  871.         if(m_ActiveWeapon != WEAPON_HAMMER && m_ActiveWeapon != WEAPON_GUN)
  872.         {
  873.             m_ActiveWeapon = WEAPON_GUN;
  874.             m_LastWeapon = WEAPON_HAMMER;
  875.         }
  876.         for(int i = 2; i < NUM_WEAPONS; i++)
  877.             m_aWeapons[i].m_Got = false;
  878.     }
  879.  
  880.     if(m_ActiveWeapon == WEAPON_NINJA && GameServer()->Collision()->IsKatanaStrip(m_Pos))
  881.     {
  882.         m_aWeapons[WEAPON_NINJA].m_Got = false;
  883.         m_ActiveWeapon = m_LastWeapon;
  884.         if(m_ActiveWeapon == WEAPON_NINJA)
  885.             m_ActiveWeapon = WEAPON_GUN;
  886.  
  887.         SetWeapon(m_ActiveWeapon);
  888.     }
  889.  
  890.     else if(TileIndex != -1 && GameServer()->Collision()->GetCollision(TileIndex) == TILE_STOPL)
  891.     {
  892.         if(m_Core.m_Vel.x > 0)
  893.         {
  894.             if((int)GameServer()->Collision()->GetPos(TileIndex).x < (int)m_Core.m_Pos.x)
  895.                 m_Core.m_Pos.x = m_PrevPos.x;
  896.             m_Core.m_Vel.x = 0;
  897.         }
  898.     }
  899.     else if(TileIndex != -1 && GameServer()->Collision()->GetCollision(TileIndex) == TILE_STOPR)
  900.     {
  901.         if(m_Core.m_Vel.x < 0)
  902.         {
  903.             if((int)GameServer()->Collision()->GetPos(TileIndex).x > (int)m_Core.m_Pos.x)
  904.                 m_Core.m_Pos.x = m_PrevPos.x;
  905.             m_Core.m_Vel.x = 0;
  906.         }
  907.     }
  908.     else if(TileIndex != -1 && GameServer()->Collision()->GetCollision(TileIndex) == TILE_STOPB)
  909.     {
  910.         if(m_Core.m_Vel.y < 0)
  911.         {
  912.             if((int)GameServer()->Collision()->GetPos(TileIndex).y > (int)m_Core.m_Pos.y)
  913.                 m_Core.m_Pos.y = m_PrevPos.y;
  914.             m_Core.m_Vel.y = 0;
  915.         }
  916.     }
  917.     else if(TileIndex != -1 && GameServer()->Collision()->GetCollision(TileIndex) == TILE_STOPT)
  918.     {
  919.         if(m_Core.m_Vel.y > 0)
  920.         {
  921.             if((int)GameServer()->Collision()->GetPos(TileIndex).y < (int)m_Core.m_Pos.y)
  922.                 m_Core.m_Pos.y = m_PrevPos.y;
  923.             if(Jumped&3 && m_Core.m_Jumped != Jumped) // check double jump
  924.                 m_Core.m_Jumped = Jumped;
  925.             m_Core.m_Vel.y = 0;
  926.         }
  927.     }
  928.  
  929.     // handle speedup tiles
  930.     int CurrentSpeedup = GameServer()->Collision()->IsSpeedup(TileIndex);
  931.     bool SpeedupTouch = false;
  932.     if(m_LastSpeedup != CurrentSpeedup && CurrentSpeedup > -1)
  933.     {
  934.         vec2 Direction;
  935.         int Force;
  936.         GameServer()->Collision()->GetSpeedup(TileIndex, &Direction, &Force);
  937.  
  938.         m_Core.m_Vel += Direction*Force;
  939.  
  940.         SpeedupTouch = true;
  941.     }
  942.  
  943.     m_LastSpeedup = CurrentSpeedup;
  944.  
  945.     // handle teleporter
  946.     z = GameServer()->Collision()->IsTeleport(TileIndex);
  947.     if(g_Config.m_SvTeleport && z)
  948.     {
  949.         // check double jump
  950.         if(Jumped&3 && m_Core.m_Jumped != Jumped)
  951.             m_Core.m_Jumped = Jumped;
  952.  
  953.         m_Core.m_HookedPlayer = -1;
  954.         m_Core.m_HookState = HOOK_RETRACTED;
  955.         m_Core.m_TriggeredEvents |= COREEVENT_HOOK_RETRACT;
  956.         m_Core.m_HookState = HOOK_RETRACTED;
  957.         m_Core.m_Pos = pzESC->m_pTeleporter[z-1];
  958.         m_Core.m_HookPos = m_Core.m_Pos;
  959.         //Resetting velocity to prevent exploit
  960.         if(g_Config.m_SvTeleportVelReset)
  961.             m_Core.m_Vel = vec2(0,0);
  962.         if(g_Config.m_SvStrip)
  963.         {
  964.             m_ActiveWeapon = WEAPON_GUN;
  965.             m_LastWeapon = WEAPON_HAMMER;
  966.             m_aWeapons[WEAPON_HAMMER].m_Got = true;
  967.             m_aWeapons[WEAPON_GUN].m_Got = true;
  968.             for(int i = 2; i < NUM_WEAPONS; i++)
  969.                 m_aWeapons[i].m_Got = false;
  970.         }
  971.     }
  972.  
  973.     if(m_FreezeTick)
  974.     {
  975.         m_FreezeTick--;
  976.         m_Core.m_Vel = vec2(0.f, 0.f);
  977.         m_Core.m_Pos = m_PrevPos;
  978.     }
  979.     if(m_BurnTick)
  980.     {
  981.         m_BurnTick--;
  982.         m_Core.m_Vel *= 0.9;
  983.         if(!(m_BurnTick%20))
  984.             GameServer()->CreateExplosion(m_Core.m_Pos, GetPlayer()->GetCID(), WEAPON_GRENADE, true);
  985.     }
  986.  
  987.     // set Position just in case it was changed
  988.     m_Pos = m_Core.m_Pos;
  989.  
  990.     // handle death-tiles and leaving gamelayer
  991.     if(!SpeedupTouch &&
  992.         (GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  993.         GameServer()->Collision()->GetCollisionAt(m_Pos.x+m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  994.         GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y-m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  995.         GameServer()->Collision()->GetCollisionAt(m_Pos.x-m_ProximityRadius/3.f, m_Pos.y+m_ProximityRadius/3.f)&CCollision::COLFLAG_DEATH ||
  996.         GameLayerClipped(m_Pos)))
  997.     {
  998.         Die(m_pPlayer->GetCID(), WEAPON_WORLD);
  999.     }
  1000.  
  1001.     // handle Weapons
  1002.     HandleWeapons();
  1003.  
  1004.     // Previnput
  1005.     m_PrevInput = m_Input;
  1006.  
  1007.     m_PrevPos = m_Core.m_Pos;
  1008.  
  1009.     if(pzESC->m_NukeLaunched && !GameServer()->Collision()->IsBunker(m_Pos))
  1010.         m_pPlayer->Nuke();
  1011.        
  1012.     /* if (!GetPlayer()->m_IsLogged)
  1013.     {
  1014.         GetPlayer()->m_Team = TEAM_SPECTATORS;
  1015.         Die(-1, -1);
  1016.         GameServer()->SendChatTarget(GetPlayer()->GetCID(), "/register <login> <pass> for registration. \n/login <login> <pass> for enter the game");
  1017.     } */
  1018.     return;
  1019. }
  1020.  
  1021. void CCharacter::TickDefered()
  1022. {
  1023.     // advance the dummy
  1024.     {
  1025.         CWorldCore TempWorld;
  1026.         m_ReckoningCore.Init(&TempWorld, GameServer()->Collision());
  1027.         m_ReckoningCore.Tick(false);
  1028.         m_ReckoningCore.Move();
  1029.         m_ReckoningCore.Quantize();
  1030.     }
  1031.  
  1032.     //lastsentcore
  1033.     vec2 StartPos = m_Core.m_Pos;
  1034.     vec2 StartVel = m_Core.m_Vel;
  1035.     bool StuckBefore = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
  1036.  
  1037.     m_Core.Move();
  1038.     bool StuckAfterMove = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
  1039.     m_Core.Quantize();
  1040.     bool StuckAfterQuant = GameServer()->Collision()->TestBox(m_Core.m_Pos, vec2(28.0f, 28.0f));
  1041.     m_Pos = m_Core.m_Pos;
  1042.  
  1043.     if(!StuckBefore && (StuckAfterMove || StuckAfterQuant))
  1044.     {
  1045.         // Hackish solution to get rid of strict-aliasing warning
  1046.         union
  1047.         {
  1048.             float f;
  1049.             unsigned u;
  1050.         }StartPosX, StartPosY, StartVelX, StartVelY;
  1051.  
  1052.         StartPosX.f = StartPos.x;
  1053.         StartPosY.f = StartPos.y;
  1054.         StartVelX.f = StartVel.x;
  1055.         StartVelY.f = StartVel.y;
  1056.  
  1057.         char aBuf[256];
  1058.         str_format(aBuf, sizeof(aBuf), "STUCK!!! %d %d %d %f %f %f %f %x %x %x %x",
  1059.             StuckBefore,
  1060.             StuckAfterMove,
  1061.             StuckAfterQuant,
  1062.             StartPos.x, StartPos.y,
  1063.             StartVel.x, StartVel.y,
  1064.             StartPosX.u, StartPosY.u,
  1065.             StartVelX.u, StartVelY.u);
  1066.         GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  1067.     }
  1068.  
  1069.     int Events = m_Core.m_TriggeredEvents;
  1070.     int Mask = CmaskAllExceptOne(m_pPlayer->GetCID());
  1071.  
  1072.     if(Events&COREEVENT_GROUND_JUMP) GameServer()->CreateSound(m_Pos, SOUND_PLAYER_JUMP, Mask);
  1073.  
  1074.     if(Events&COREEVENT_HOOK_ATTACH_PLAYER) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_PLAYER, CmaskAll());
  1075.     if(Events&COREEVENT_HOOK_ATTACH_GROUND) GameServer()->CreateSound(m_Pos, SOUND_HOOK_ATTACH_GROUND, Mask);
  1076.     if(Events&COREEVENT_HOOK_HIT_NOHOOK) GameServer()->CreateSound(m_Pos, SOUND_HOOK_NOATTACH, Mask);
  1077.  
  1078.  
  1079.     if(m_pPlayer->GetTeam() == TEAM_SPECTATORS)
  1080.     {
  1081.         m_Pos.x = m_Input.m_TargetX;
  1082.         m_Pos.y = m_Input.m_TargetY;
  1083.     }
  1084.  
  1085.     // update the m_SendCore if needed
  1086.     {
  1087.         CNetObj_Character Predicted;
  1088.         CNetObj_Character Current;
  1089.         mem_zero(&Predicted, sizeof(Predicted));
  1090.         mem_zero(&Current, sizeof(Current));
  1091.         m_ReckoningCore.Write(&Predicted);
  1092.         m_Core.Write(&Current);
  1093.  
  1094.         // only allow dead reackoning for a top of 3 seconds
  1095.         if(m_ReckoningTick+Server()->TickSpeed()*3 < Server()->Tick() || mem_comp(&Predicted, &Current, sizeof(CNetObj_Character)) != 0)
  1096.         {
  1097.             m_ReckoningTick = Server()->Tick();
  1098.             m_SendCore = m_Core;
  1099.             m_ReckoningCore = m_Core;
  1100.         }
  1101.     }
  1102. }
  1103.  
  1104. bool CCharacter::IncreaseHealth(int Amount)
  1105. {
  1106.     if(m_Health >= 10)
  1107.         return false;
  1108.     m_Health = clamp(m_Health+Amount, 0, 10);
  1109.     return true;
  1110. }
  1111.  
  1112. bool CCharacter::IncreaseArmor(int Amount)
  1113. {
  1114.     if(m_Armor >= 10)
  1115.         return false;
  1116.     m_Armor = clamp(m_Armor+Amount, 0, 10);
  1117.     return true;
  1118. }
  1119.  
  1120. void CCharacter::Die(int Killer, int Weapon)
  1121. {
  1122.     // we got to wait 0.5 secs before respawning
  1123.     m_pPlayer->m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
  1124.     int ModeSpecial = GameServer()->m_pController->OnCharacterDeath(this, GameServer()->m_apPlayers[Killer], Weapon);
  1125.  
  1126.     char aBuf[256];
  1127.     str_format(aBuf, sizeof(aBuf), "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d",
  1128.         Killer, Server()->ClientName(Killer),
  1129.         m_pPlayer->GetCID(), Server()->ClientName(m_pPlayer->GetCID()), Weapon, ModeSpecial);
  1130.     GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game", aBuf);
  1131.    
  1132.     if(OnSpree()) {
  1133.             GameServer()->CreateSound(m_Pos, SOUND_GRENADE_EXPLODE);
  1134.             GameServer()->CreateExplosion(m_Pos, m_pPlayer->GetCID(), WEAPON_RIFLE, true); }
  1135.     if(GameServer()->m_apPlayers[Killer]->GetCharacter())
  1136.             GameServer()->m_apPlayers[Killer]->GetCharacter()->SpreeAdd();
  1137.     SpreeEnd(Killer);
  1138.    
  1139. /*  if(GameServer()->m_apPlayers[Killer]->GetCharacter())
  1140.        {
  1141.             GameServer()->m_apPlayers[Killer]->m_Spree++;
  1142.        }
  1143.        
  1144.     m_pPlayer->m_Spree = 0;  */
  1145.     // send the kill message
  1146.     CNetMsg_Sv_KillMsg Msg;
  1147.     Msg.m_Killer = Killer;
  1148.     Msg.m_Victim = m_pPlayer->GetCID();
  1149.     Msg.m_Weapon = Weapon;
  1150.     Msg.m_ModeSpecial = ModeSpecial;
  1151.     Server()->SendPackMsg(&Msg, MSGFLAG_VITAL, -1);
  1152.     // a nice sound
  1153.     GameServer()->CreateSound(m_Pos, SOUND_PLAYER_DIE);
  1154.     GameServer()->Update(GameServer()->m_apPlayers[Killer]->name, m_pPlayer->GetCID());
  1155.  
  1156.     // this is for auto respawn after 3 secs
  1157.     m_pPlayer->m_DieTick = Server()->Tick();
  1158.  
  1159.     m_Alive = false;
  1160.     GameServer()->m_World.RemoveEntity(this);
  1161.     GameServer()->m_World.m_Core.m_apCharacters[m_pPlayer->GetCID()] = 0;
  1162.     GameServer()->CreateDeath(m_Pos, m_pPlayer->GetCID());
  1163.  
  1164.     if(m_HookedItem)
  1165.         m_HookedItem->Reset();
  1166.     m_Item = 0;
  1167.     m_HookedItem = 0;
  1168. }
  1169.  
  1170. bool CCharacter::TakeDamage(vec2 Force, int Dmg, int From, int Weapon)
  1171. {
  1172.     /* if(m_pPlayer->GetTeam() == TEAM_BLUE && (Weapon == WEAPON_GRENADE || Weapon == WEAPON_HAMMER))
  1173.         m_Core.m_Vel += Force;
  1174.     if(Weapon == WEAPON_GRENADE && From == m_pPlayer->GetCID() && m_pPlayer->GetTeam() == TEAM_BLUE && m_Item == HITEM_GRENADE)
  1175.         m_Core.m_Vel += Force; // Bigger rocketjump for upgraded grenade :3
  1176.  
  1177.     if(m_pPlayer->GetTeam() == TEAM_RED)
  1178.     {
  1179.         vec2 AddVel = vec2(0, 0);
  1180.         if(Weapon == WEAPON_HAMMER)
  1181.             m_Item ? AddVel = Force*0.7f : AddVel = Force;
  1182.         else if(Weapon == WEAPON_GUN)
  1183.         {
  1184.             if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item != HITEM_GUN)
  1185.                 m_Item ? AddVel = Force*0.7f : AddVel = Force;
  1186.             else if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item == HITEM_GUN)
  1187.                 m_Item ? AddVel = Force : AddVel = Force*1.35f;
  1188.         }
  1189.         else if(Weapon == WEAPON_SHOTGUN)
  1190.         {
  1191.             if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item != HITEM_SHOTGUN)
  1192.                 m_Item ? AddVel = Force*0.7f : AddVel = Force;
  1193.             else if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item == HITEM_SHOTGUN)
  1194.                 m_Item ? AddVel = Force : AddVel = Force*1.3f;
  1195.         }
  1196.         else if(Weapon == WEAPON_GRENADE)
  1197.         {
  1198.             if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item != HITEM_GRENADE)
  1199.             {
  1200.                 m_Item ? AddVel = Force : AddVel = Force*2.0f;
  1201.                 m_Item ? m_BurnTick = Server()->TickSpeed()*1.5f : m_BurnTick = Server()->TickSpeed()*2.0f;
  1202.             }
  1203.             else if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item == HITEM_GRENADE)
  1204.             {
  1205.                 m_Item ? AddVel = Force*2 : AddVel = Force*3.0f;
  1206.                 m_Item ? m_BurnTick = Server()->TickSpeed()*2.0f : m_BurnTick = Server()->TickSpeed()*3.0f;
  1207.             }
  1208.         }
  1209.         else if(Weapon == WEAPON_RIFLE)
  1210.         {
  1211.             if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item != HITEM_RIFLE)
  1212.                 m_Item ? m_FreezeTick = Server()->TickSpeed()*1.0f : m_FreezeTick = Server()->TickSpeed()*1.5f;
  1213.             else if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item == HITEM_RIFLE)
  1214.                 m_Item ? m_FreezeTick = Server()->TickSpeed()*1.5f : m_FreezeTick = Server()->TickSpeed()*2.0f;
  1215.         }
  1216.         if(m_BurnTick)
  1217.             AddVel *= 2.5f;
  1218.         m_Core.m_Vel += AddVel;
  1219.     }
  1220.  
  1221.     return false; */
  1222.             m_Core.m_Vel += Force;
  1223.     if (From == m_pPlayer->GetCID())
  1224.         return false;
  1225.     if(GameServer()->m_pController->IsFriendlyFire(m_pPlayer->GetCID(), From))
  1226.         return false;
  1227.  
  1228.     // m_pPlayer only inflicts half damage on self
  1229.     if(From == m_pPlayer->GetCID())
  1230.         Dmg = max(1, Dmg/2);
  1231.  
  1232.     m_DamageTaken++;
  1233.  
  1234.     // create healthmod indicator
  1235.     if(Server()->Tick() < m_DamageTakenTick+25)
  1236.     {
  1237.         // make sure that the damage indicators doesn't group together
  1238.         if (Weapon != WEAPON_RIFLE)
  1239.             GameServer()->CreateDamageInd(m_Pos, m_DamageTaken*0.25f, Dmg);
  1240.     }
  1241.     else
  1242.     {
  1243.         m_DamageTaken = 0;
  1244.         GameServer()->CreateDamageInd(m_Pos, 0, Dmg);
  1245.     }
  1246.  
  1247.     if(Dmg && Weapon != WEAPON_RIFLE)
  1248.     {
  1249.         if(m_Armor)
  1250.         {
  1251.             if(Dmg > 1)
  1252.             {
  1253.                 m_Health--;
  1254.                 Dmg--;
  1255.             }
  1256.  
  1257.             if(Dmg > m_Armor)
  1258.             {
  1259.                 Dmg -= m_Armor;
  1260.                 m_Armor = 0;
  1261.             }
  1262.             else
  1263.             {
  1264.                 m_Armor -= Dmg;
  1265.                 Dmg = 0;
  1266.             }
  1267.         }
  1268.  
  1269.         m_Health -= Dmg;
  1270.     }
  1271.     if(Weapon == WEAPON_RIFLE)
  1272.         {
  1273.             /* if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item != HITEM_RIFLE)
  1274.                 m_Item ? m_FreezeTick = Server()->Tick() + Server()->TickSpeed() : m_FreezeTick = Server()->Tick() + Server()->TickSpeed()*1.5f;
  1275.             else if(GameServer()->m_apPlayers[From] && GameServer()->m_apPlayers[From]->GetCharacter() && GameServer()->m_apPlayers[From]->GetCharacter()->m_Item != HITEM_RIFLE)
  1276.                 m_Item ? m_FreezeTick = Server()->Tick() + Server()->TickSpeed()*1.5f : m_FreezeTick = Server()->Tick() + Server()->TickSpeed()*2.f;
  1277.             */
  1278.             float A = g_Config.m_SvTestFreeze;
  1279.             float B = g_Config.m_SvTestFreeze2;
  1280.             m_Item ? m_FreezeTick = A : m_FreezeTick = B;
  1281.            
  1282.         }
  1283.  
  1284.     m_DamageTakenTick = Server()->Tick();
  1285.  
  1286.     // do damage Hit sound
  1287.     if(From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
  1288.     {
  1289.         int Mask = CmaskOne(From);
  1290.         for(int i = 0; i < MAX_CLIENTS; i++)
  1291.         {
  1292.             if(GameServer()->m_apPlayers[i] && GameServer()->m_apPlayers[i]->GetTeam() == TEAM_SPECTATORS && GameServer()->m_apPlayers[i]->m_SpectatorID == From)
  1293.                 Mask |= CmaskOne(i);
  1294.         }
  1295.         if (Weapon != WEAPON_RIFLE)
  1296.             GameServer()->CreateSound(GameServer()->m_apPlayers[From]->m_ViewPos, SOUND_HIT, Mask);
  1297.     }
  1298.  
  1299.     // check for death
  1300.     if(m_Health <= 0)
  1301.     {
  1302.         Die(From, Weapon);
  1303. /*      if(Spree <= 4)
  1304.                 {
  1305.                     GameServer()->m_apPlayers[From]->m_Exp += 1;
  1306.                     GameServer()->m_apPlayers[From]->m_Score += 1;         
  1307.                 } */
  1308.         if(Exp2 == true)
  1309.                 {
  1310.                     GameServer()->m_apPlayers[From]->m_Exp += 2;
  1311.                     GameServer()->m_apPlayers[From]->m_Score += 2;
  1312.                     char b[128];
  1313.                     str_format(b, sizeof(b), "Exp x2 -> %d/%d", GameServer()->m_apPlayers[From]->m_Exp, GameServer()->m_apPlayers[From]->m_Lvl);
  1314.                     GameServer()->SendChatTarget(From, b);
  1315.                 }
  1316.         else
  1317.                 {
  1318.                     GameServer()->m_apPlayers[From]->m_Exp += 1;
  1319.                     GameServer()->m_apPlayers[From]->m_Score += 1;         
  1320.                     //GameServer()->Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "game x1", GameServer()->m_apPlayers[From]->m_Exp);                 
  1321.                 }
  1322.        
  1323.         char a[128];
  1324.         str_format(a, sizeof(a), "Exp -> %d/%d", GameServer()->m_apPlayers[From]->m_Exp, GameServer()->m_apPlayers[From]->m_Lvl);
  1325.         GameServer()->SendChatTarget(From, a);
  1326.         // GameServer()->Update(GetPlayer()->name, GetPlayer()->GetCID());
  1327.         //GameServer()->m_apPlayers[From]->GameServer()->CreateLolText(this, false, vec2(0,-75), vec2 (0,-1), 200, "1");
  1328.  
  1329.         // set attacker's face to happy (taunt!)
  1330.         if (From >= 0 && From != m_pPlayer->GetCID() && GameServer()->m_apPlayers[From])
  1331.         {
  1332.             CCharacter *pChr = GameServer()->m_apPlayers[From]->GetCharacter();
  1333.             if (pChr)
  1334.             {
  1335.                 pChr->m_EmoteType = EMOTE_HAPPY;
  1336.                 pChr->m_EmoteStop = Server()->Tick() + Server()->TickSpeed();
  1337.             }
  1338.         }
  1339.  
  1340.         return false;
  1341.     }
  1342.     if (Weapon != WEAPON_RIFLE)
  1343.     {
  1344.         if (Dmg > 2)
  1345.             GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_LONG);
  1346.         else
  1347.             GameServer()->CreateSound(m_Pos, SOUND_PLAYER_PAIN_SHORT);
  1348.     }
  1349.  
  1350.     m_EmoteType = EMOTE_PAIN;
  1351.     m_EmoteStop = Server()->Tick() + 500 * Server()->TickSpeed() / 1000;
  1352.  
  1353.     return true;
  1354. }
  1355.  
  1356. void CCharacter::SetZomb()
  1357. {
  1358.     m_ActiveWeapon = WEAPON_HAMMER;
  1359.     m_LastWeapon = WEAPON_HAMMER;
  1360.     m_QueuedWeapon = -1;
  1361.  
  1362.     if(m_Item && (m_Item != HITEM_GUN || m_Item != HITEM_GRENADE))
  1363.     {
  1364.         GameServer()->SendBroadcast("Your human item transfered into a zombie item!", m_pPlayer->GetCID());
  1365.         GameServer()->CreateSound(m_Pos, SOUND_WEAPON_SWITCH);
  1366.         SetEmote(EMOTE_ANGRY, Server()->Tick() + 1200 * Server()->TickSpeed() / 1000);
  1367.         m_Item = ZITEM_HAMMER;
  1368.     }
  1369.     else
  1370.         m_Item = 0;
  1371.    
  1372.     if(m_HookedItem)
  1373.         m_HookedItem->Reset();
  1374.     m_HookedItem = 0;
  1375.     m_Armor = 0;
  1376. }
  1377.  
  1378. void CCharacter::Snap(int SnappingClient)
  1379. {
  1380.     if(NetworkClipped(SnappingClient))
  1381.         return;
  1382.  
  1383.     CNetObj_Character *pCharacter = static_cast<CNetObj_Character *>(Server()->SnapNewItem(NETOBJTYPE_CHARACTER, m_pPlayer->GetCID(), sizeof(CNetObj_Character)));
  1384.     if(!pCharacter)
  1385.         return;
  1386.  
  1387.     // write down the m_Core
  1388.     if(!m_ReckoningTick || GameServer()->m_World.m_Paused)
  1389.     {
  1390.         // no dead reckoning when paused because the client doesn't know
  1391.         // how far to perform the reckoning
  1392.         pCharacter->m_Tick = 0;
  1393.         m_Core.Write(pCharacter);
  1394.     }
  1395.     else
  1396.     {
  1397.         pCharacter->m_Tick = m_ReckoningTick;
  1398.         m_SendCore.Write(pCharacter);
  1399.     }
  1400.  
  1401.     // set emote
  1402.     if (m_EmoteStop < Server()->Tick())
  1403.     {
  1404.         m_EmoteType = EMOTE_NORMAL;
  1405.         m_EmoteStop = -1;
  1406.     }
  1407.  
  1408.     pCharacter->m_Emote = m_EmoteType;
  1409.  
  1410.     pCharacter->m_AmmoCount = 0;
  1411.     pCharacter->m_Health = 0;
  1412.     pCharacter->m_Armor = 0;
  1413.  
  1414.     pCharacter->m_Weapon = m_ActiveWeapon;
  1415.     pCharacter->m_AttackTick = m_AttackTick;
  1416.  
  1417.     pCharacter->m_Direction = m_Input.m_Direction;
  1418.  
  1419.     if(m_pPlayer->GetCID() == SnappingClient || SnappingClient == -1 ||
  1420.         (!g_Config.m_SvStrictSpectateMode && m_pPlayer->GetCID() == GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID))
  1421.     {
  1422.         pCharacter->m_Health = m_Health;
  1423.         pCharacter->m_Armor = m_Armor;
  1424.         if(m_aWeapons[m_ActiveWeapon].m_Ammo > 0)
  1425.             pCharacter->m_AmmoCount = m_aWeapons[m_ActiveWeapon].m_Ammo;
  1426.     }
  1427.  
  1428.     if(pCharacter->m_Emote == EMOTE_NORMAL)
  1429.     {
  1430.         if(250 - ((Server()->Tick() - m_LastAction)%(250)) < 5)
  1431.             pCharacter->m_Emote = EMOTE_BLINK;
  1432.     }
  1433.  
  1434.     pCharacter->m_PlayerFlags = GetPlayer()->m_PlayerFlags;
  1435. }
  1436.  
  1437. char SpreeNote[4][32] = { "is(Give Unlimited GUN)", "is(Give Fire delay faster) ", "is(Give x2 rates)", "is unstoppable" };
  1438.  
  1439. bool CCharacter::OnSpree()
  1440. {
  1441.     if(Spree >= 5)
  1442.         return true;
  1443.     return false;
  1444. }
  1445.  
  1446. void CCharacter::SpreeAdd()
  1447. {
  1448.     Spree++;
  1449.     if(Spree > 5)
  1450.     {
  1451.         Exp2 = true;
  1452.     }
  1453.     if(Spree % 5 == 0)
  1454.     {
  1455.         int p = (int)Spree/5-1;
  1456.         if(p > 3)
  1457.             p = 3;
  1458.         char aBuf[512];
  1459.         str_format(aBuf, sizeof(aBuf), "%s %s with %d kills!", Server()->ClientName(m_pPlayer->GetCID()), SpreeNote[p], Spree);
  1460.         GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  1461.     }
  1462. }
  1463.  
  1464. void CCharacter::SpreeEnd(int killer)
  1465. {
  1466.     if(Spree >= 5)
  1467.     {
  1468.         char aBuf[512];
  1469.         str_format(aBuf, sizeof(aBuf), "%s %d-kills killing spree was ended by %s", Server()->ClientName(m_pPlayer->GetCID()), Spree, Server()->ClientName(killer));
  1470.         GameServer()->SendChat(-1, CGameContext::CHAT_ALL, aBuf);
  1471.     }
  1472.     Spree = 0;
  1473. }
Add Comment
Please, Sign In to add comment