/* (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" #include #include #include #include #include "character.h" static constexpr int PickupPhysSize = 14; CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType, int Layer, int Number) : CEntity(pGameWorld, CGameWorld::ENTTYPE_PICKUP, vec2(0, 0), PickupPhysSize) { m_Type = Type; m_Subtype = SubType; m_Layer = Layer; m_Number = Number; Reset(); GameWorld()->InsertEntity(this); } void CPickup::Reset() { } void CPickup::Tick() { Move(); // Check if a player intersected us CCharacter *apEnts[MAX_CLIENTS]; int Num = GameWorld()->FindEntities(m_Pos, 20.0f, (CEntity **)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for(int i = 0; i < Num; ++i) { CCharacter *pChr = apEnts[i]; if(pChr && pChr->IsAlive()) { if(m_Layer == LAYER_SWITCH && m_Number > 0 && !Switchers()[m_Number].m_Status[pChr->Team()]) continue; bool Sound = false; // player picked us up, is someone was hooking us, let them go switch(m_Type) { case POWERUP_HEALTH: if(pChr->Freeze()) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_HEALTH, pChr->TeamMask()); break; case POWERUP_ARMOR: if(pChr->Team() == TEAM_SUPER) continue; for(int j = WEAPON_SHOTGUN; j < NUM_WEAPONS; j++) { if(pChr->GetWeaponGot(j)) { pChr->SetWeaponGot(j, false); pChr->SetWeaponAmmo(j, 0); Sound = true; } } pChr->SetNinjaActivationDir(vec2(0, 0)); pChr->SetNinjaActivationTick(-500); pChr->SetNinjaCurrentMoveTime(0); if(Sound) { pChr->SetLastWeapon(WEAPON_GUN); GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR, pChr->TeamMask()); } if(pChr->GetActiveWeapon() >= WEAPON_SHOTGUN) pChr->SetActiveWeapon(WEAPON_HAMMER); break; case POWERUP_ARMOR_SHOTGUN: 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); GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR, pChr->TeamMask()); } if(pChr->GetActiveWeapon() == WEAPON_SHOTGUN) pChr->SetActiveWeapon(WEAPON_HAMMER); break; case POWERUP_ARMOR_GRENADE: 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); GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR, pChr->TeamMask()); } if(pChr->GetActiveWeapon() == WEAPON_GRENADE) pChr->SetActiveWeapon(WEAPON_HAMMER); break; case POWERUP_ARMOR_NINJA: if(pChr->Team() == TEAM_SUPER) continue; pChr->SetNinjaActivationDir(vec2(0, 0)); pChr->SetNinjaActivationTick(-500); pChr->SetNinjaCurrentMoveTime(0); break; case POWERUP_ARMOR_LASER: 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); GameServer()->CreateSound(m_Pos, SOUND_PICKUP_ARMOR, pChr->TeamMask()); } if(pChr->GetActiveWeapon() == WEAPON_LASER) pChr->SetActiveWeapon(WEAPON_HAMMER); break; case POWERUP_WEAPON: if(m_Subtype >= 0 && m_Subtype < NUM_WEAPONS && (!pChr->GetWeaponGot(m_Subtype) || pChr->GetWeaponAmmo(m_Subtype) != -1)) { pChr->GiveWeapon(m_Subtype); if(m_Subtype == WEAPON_GRENADE) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_GRENADE, pChr->TeamMask()); else if(m_Subtype == WEAPON_SHOTGUN) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN, pChr->TeamMask()); else if(m_Subtype == WEAPON_LASER) GameServer()->CreateSound(m_Pos, SOUND_PICKUP_SHOTGUN, pChr->TeamMask()); if(pChr->GetPlayer()) GameServer()->SendWeaponPickup(pChr->GetPlayer()->GetCID(), m_Subtype); } break; case POWERUP_NINJA: { // activate ninja on target player pChr->GiveNinja(); break; } default: break; }; } } } void CPickup::TickPaused() { } void CPickup::Snap(int SnappingClient) { if(NetworkClipped(SnappingClient)) return; CCharacter *pChar = GameServer()->GetPlayerChar(SnappingClient); if(SnappingClient != SERVER_DEMO_CLIENT && (GameServer()->m_apPlayers[SnappingClient]->GetTeam() == TEAM_SPECTATORS || GameServer()->m_apPlayers[SnappingClient]->IsPaused()) && GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID != SPEC_FREEVIEW) pChar = GameServer()->GetPlayerChar(GameServer()->m_apPlayers[SnappingClient]->m_SpectatorID); int SnappingClientVersion = SnappingClient != SERVER_DEMO_CLIENT ? GameServer()->GetClientVersion(SnappingClient) : CLIENT_VERSIONNR; CNetObj_EntityEx *pEntData = 0; if(SnappingClientVersion >= VERSION_DDNET_SWITCH && (m_Layer == LAYER_SWITCH || length(m_Core) > 0)) pEntData = static_cast(Server()->SnapNewItem(NETOBJTYPE_ENTITYEX, GetID(), sizeof(CNetObj_EntityEx))); if(pEntData) { pEntData->m_SwitchNumber = m_Number; pEntData->m_Layer = m_Layer; pEntData->m_EntityClass = ENTITYCLASS_PICKUP; } else { int Tick = (Server()->Tick() % Server()->TickSpeed()) % 11; if(pChar && pChar->IsAlive() && m_Layer == LAYER_SWITCH && m_Number > 0 && !Switchers()[m_Number].m_Status[pChar->Team()] && !Tick) return; } int Size = Server()->IsSixup(SnappingClient) ? 3 * 4 : sizeof(CNetObj_Pickup); CNetObj_Pickup *pPickup = static_cast(Server()->SnapNewItem(NETOBJTYPE_PICKUP, GetID(), Size)); if(!pPickup) return; pPickup->m_X = (int)m_Pos.x; pPickup->m_Y = (int)m_Pos.y; pPickup->m_Type = m_Type; if(SnappingClientVersion < VERSION_DDNET_WEAPON_SHIELDS) { if(m_Type >= POWERUP_ARMOR_SHOTGUN && m_Type <= POWERUP_ARMOR_LASER) { pPickup->m_Type = POWERUP_ARMOR; } } if(Server()->IsSixup(SnappingClient)) { if(m_Type == POWERUP_WEAPON) pPickup->m_Type = m_Subtype == WEAPON_SHOTGUN ? 3 : m_Subtype == WEAPON_GRENADE ? 2 : 4; else if(m_Type == POWERUP_NINJA) pPickup->m_Type = 5; } else pPickup->m_Subtype = m_Subtype; } void CPickup::Move() { if(Server()->Tick() % int(Server()->TickSpeed() * 0.15f) == 0) { int Flags; int index = GameServer()->Collision()->IsMover(m_Pos.x, m_Pos.y, &Flags); if(index) { m_Core = GameServer()->Collision()->CpSpeed(index, Flags); } m_Pos += m_Core; } }