2019-04-11 22:46:54 +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 "pickup.h"
|
2020-09-26 19:41:58 +00:00
|
|
|
#include "character.h"
|
2022-06-16 16:06:35 +00:00
|
|
|
#include <game/collision.h>
|
2020-09-26 19:41:58 +00:00
|
|
|
#include <game/generated/protocol.h>
|
2022-05-29 12:11:29 +00:00
|
|
|
#include <game/mapitems.h>
|
2019-04-11 22:46:54 +00:00
|
|
|
|
|
|
|
void CPickup::Tick()
|
|
|
|
{
|
|
|
|
Move();
|
|
|
|
// Check if a player intersected us
|
2022-11-09 22:07:15 +00:00
|
|
|
CEntity *apEnts[MAX_CLIENTS];
|
|
|
|
int Num = GameWorld()->FindEntities(m_Pos, 20.0f, apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
|
2020-09-26 19:41:58 +00:00
|
|
|
for(int i = 0; i < Num; ++i)
|
|
|
|
{
|
2022-11-09 22:07:15 +00:00
|
|
|
auto *pChr = static_cast<CCharacter *>(apEnts[i]);
|
2022-05-26 21:06:17 +00:00
|
|
|
if(pChr)
|
2019-04-11 22:46:54 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
if(GameWorld()->m_WorldConfig.m_IsVanilla && distance(m_Pos, pChr->m_Pos) >= 20.0f * 2) // pickup distance is shorter on vanilla due to using ClosestEntity
|
|
|
|
continue;
|
2022-06-30 22:36:32 +00:00
|
|
|
if(m_Layer == LAYER_SWITCH && m_Number > 0 && m_Number < (int)Switchers().size() && !Switchers()[m_Number].m_aStatus[pChr->Team()])
|
2021-09-19 12:14:00 +00:00
|
|
|
continue;
|
2019-04-11 22:46:54 +00:00
|
|
|
bool sound = false;
|
|
|
|
// player picked us up, is someone was hooking us, let them go
|
2020-09-26 19:41:58 +00:00
|
|
|
switch(m_Type)
|
2019-04-11 22:46:54 +00:00
|
|
|
{
|
2020-09-26 19:41:58 +00:00
|
|
|
case POWERUP_HEALTH:
|
|
|
|
//pChr->Freeze();
|
|
|
|
break;
|
2019-04-11 22:46:54 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
case POWERUP_ARMOR:
|
|
|
|
if(!GameWorld()->m_WorldConfig.m_IsDDRace || !GameWorld()->m_WorldConfig.m_PredictDDRace)
|
|
|
|
continue;
|
2022-06-30 17:29:58 +00:00
|
|
|
if(pChr->IsSuper())
|
2020-09-26 19:41:58 +00:00
|
|
|
continue;
|
2022-03-20 11:57:50 +00:00
|
|
|
for(int j = WEAPON_SHOTGUN; j < NUM_WEAPONS; j++)
|
2020-09-26 19:41:58 +00:00
|
|
|
{
|
2022-03-20 11:57:50 +00:00
|
|
|
if(pChr->GetWeaponGot(j))
|
2019-04-11 22:46:54 +00:00
|
|
|
{
|
2022-03-20 11:57:50 +00:00
|
|
|
pChr->SetWeaponGot(j, false);
|
|
|
|
pChr->SetWeaponAmmo(j, 0);
|
2020-09-26 19:41:58 +00:00
|
|
|
sound = true;
|
2019-04-11 22:46:54 +00:00
|
|
|
}
|
2020-09-26 19:41:58 +00:00
|
|
|
}
|
|
|
|
pChr->SetNinjaActivationDir(vec2(0, 0));
|
|
|
|
pChr->SetNinjaActivationTick(-500);
|
|
|
|
pChr->SetNinjaCurrentMoveTime(0);
|
|
|
|
if(sound)
|
|
|
|
pChr->SetLastWeapon(WEAPON_GUN);
|
|
|
|
if(pChr->GetActiveWeapon() >= WEAPON_SHOTGUN)
|
|
|
|
pChr->SetActiveWeapon(WEAPON_HAMMER);
|
|
|
|
break;
|
2019-04-11 22:46:54 +00:00
|
|
|
|
2022-02-17 23:51:02 +00:00
|
|
|
case POWERUP_ARMOR_SHOTGUN:
|
|
|
|
if(!GameWorld()->m_WorldConfig.m_IsDDRace || !GameWorld()->m_WorldConfig.m_PredictDDRace)
|
|
|
|
continue;
|
|
|
|
if(pChr->Team() == TEAM_SUPER)
|
|
|
|
continue;
|
|
|
|
if(pChr->GetWeaponGot(WEAPON_SHOTGUN))
|
|
|
|
{
|
|
|
|
pChr->SetWeaponGot(WEAPON_SHOTGUN, false);
|
|
|
|
pChr->SetWeaponAmmo(WEAPON_SHOTGUN, 0);
|
|
|
|
pChr->SetLastWeapon(WEAPON_GUN);
|
|
|
|
}
|
|
|
|
if(pChr->GetActiveWeapon() == WEAPON_SHOTGUN)
|
|
|
|
pChr->SetActiveWeapon(WEAPON_HAMMER);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case POWERUP_ARMOR_GRENADE:
|
|
|
|
if(!GameWorld()->m_WorldConfig.m_IsDDRace || !GameWorld()->m_WorldConfig.m_PredictDDRace)
|
|
|
|
continue;
|
|
|
|
if(pChr->Team() == TEAM_SUPER)
|
|
|
|
continue;
|
|
|
|
if(pChr->GetWeaponGot(WEAPON_GRENADE))
|
|
|
|
{
|
|
|
|
pChr->SetWeaponGot(WEAPON_GRENADE, false);
|
|
|
|
pChr->SetWeaponAmmo(WEAPON_GRENADE, 0);
|
|
|
|
pChr->SetLastWeapon(WEAPON_GUN);
|
|
|
|
}
|
|
|
|
if(pChr->GetActiveWeapon() == WEAPON_GRENADE)
|
|
|
|
pChr->SetActiveWeapon(WEAPON_HAMMER);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case POWERUP_ARMOR_NINJA:
|
|
|
|
if(!GameWorld()->m_WorldConfig.m_IsDDRace || !GameWorld()->m_WorldConfig.m_PredictDDRace)
|
|
|
|
continue;
|
|
|
|
if(pChr->Team() == TEAM_SUPER)
|
|
|
|
continue;
|
|
|
|
pChr->SetNinjaActivationDir(vec2(0, 0));
|
|
|
|
pChr->SetNinjaActivationTick(-500);
|
|
|
|
pChr->SetNinjaCurrentMoveTime(0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case POWERUP_ARMOR_LASER:
|
|
|
|
if(!GameWorld()->m_WorldConfig.m_IsDDRace || !GameWorld()->m_WorldConfig.m_PredictDDRace)
|
|
|
|
continue;
|
|
|
|
if(pChr->Team() == TEAM_SUPER)
|
|
|
|
continue;
|
|
|
|
if(pChr->GetWeaponGot(WEAPON_LASER))
|
|
|
|
{
|
|
|
|
pChr->SetWeaponGot(WEAPON_LASER, false);
|
|
|
|
pChr->SetWeaponAmmo(WEAPON_LASER, 0);
|
|
|
|
pChr->SetLastWeapon(WEAPON_GUN);
|
|
|
|
}
|
|
|
|
if(pChr->GetActiveWeapon() == WEAPON_LASER)
|
|
|
|
pChr->SetActiveWeapon(WEAPON_HAMMER);
|
|
|
|
break;
|
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
case POWERUP_WEAPON:
|
|
|
|
if(m_Subtype >= 0 && m_Subtype < NUM_WEAPONS && (!pChr->GetWeaponGot(m_Subtype) || pChr->GetWeaponAmmo(m_Subtype) != -1))
|
|
|
|
pChr->GiveWeapon(m_Subtype);
|
|
|
|
break;
|
2019-04-11 22:46:54 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
case POWERUP_NINJA:
|
|
|
|
{
|
|
|
|
// activate ninja on target player
|
|
|
|
pChr->GiveNinja();
|
|
|
|
break;
|
|
|
|
}
|
2019-05-04 20:16:51 +00:00
|
|
|
|
2020-09-26 19:41:58 +00:00
|
|
|
default:
|
|
|
|
break;
|
2019-04-11 22:46:54 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPickup::Move()
|
|
|
|
{
|
2022-11-06 09:47:41 +00:00
|
|
|
if(GameWorld()->GameTick() % (int)(GameWorld()->GameTickSpeed() * 0.15f) == 0)
|
2019-04-11 22:46:54 +00:00
|
|
|
{
|
|
|
|
int Flags;
|
2020-09-26 19:41:58 +00:00
|
|
|
int index = Collision()->IsMover(m_Pos.x, m_Pos.y, &Flags);
|
|
|
|
if(index)
|
2019-04-11 22:46:54 +00:00
|
|
|
{
|
2021-05-27 07:45:41 +00:00
|
|
|
m_IsCoreActive = true;
|
2020-09-26 19:41:58 +00:00
|
|
|
m_Core = Collision()->CpSpeed(index, Flags);
|
2019-04-11 22:46:54 +00:00
|
|
|
}
|
|
|
|
m_Pos += m_Core;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-19 12:14:00 +00:00
|
|
|
CPickup::CPickup(CGameWorld *pGameWorld, int ID, CNetObj_Pickup *pPickup, const CNetObj_EntityEx *pEntEx) :
|
2020-09-26 19:41:58 +00:00
|
|
|
CEntity(pGameWorld, CGameWorld::ENTTYPE_PICKUP)
|
2019-04-11 22:46:54 +00:00
|
|
|
{
|
|
|
|
m_Pos.x = pPickup->m_X;
|
|
|
|
m_Pos.y = pPickup->m_Y;
|
|
|
|
m_Type = pPickup->m_Type;
|
|
|
|
m_Subtype = pPickup->m_Subtype;
|
|
|
|
m_Core = vec2(0.f, 0.f);
|
2021-05-27 07:45:41 +00:00
|
|
|
m_IsCoreActive = false;
|
2019-04-11 22:46:54 +00:00
|
|
|
m_ID = ID;
|
2019-06-18 01:04:03 +00:00
|
|
|
m_Layer = LAYER_GAME;
|
|
|
|
m_Number = 0;
|
2021-09-19 12:14:00 +00:00
|
|
|
|
|
|
|
if(pEntEx)
|
|
|
|
{
|
|
|
|
m_Layer = pEntEx->m_Layer;
|
|
|
|
m_Number = pEntEx->m_SwitchNumber;
|
|
|
|
}
|
2019-04-11 22:46:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPickup::FillInfo(CNetObj_Pickup *pPickup)
|
|
|
|
{
|
|
|
|
pPickup->m_X = (int)m_Pos.x;
|
|
|
|
pPickup->m_Y = (int)m_Pos.y;
|
|
|
|
pPickup->m_Type = m_Type;
|
|
|
|
pPickup->m_Subtype = m_Subtype;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CPickup::Match(CPickup *pPickup)
|
|
|
|
{
|
|
|
|
if(pPickup->m_Type != m_Type || pPickup->m_Subtype != m_Subtype)
|
|
|
|
return false;
|
|
|
|
if(distance(pPickup->m_Pos, m_Pos) > 2.0f)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|