bool CGameControllerOpenFNG::CanJoinTeam(int Team, int NotThisID) { int Can = IGameController::CanJoinTeam(Team, NotThisID); if (!Can) return false; CCharacter *pChr = CHAR(NotThisID); return !pChr || pChr->GetFreezeTicks() <= 0; }
void CGameControllerSoloFNG::DoHookers() { for(int i = 0; i < MAX_CLIENTS; i++) { CCharacter *pChr = CHAR(i); if (!pChr) continue; int Hooking = pChr->GetHookedPlayer(); if (Hooking >= 0) { CCharacter *pVic = CHAR(Hooking); if (!pVic || (/*pVic->GetPlayer()->GetTeam() != pChr->GetPlayer()->GetTeam() && */pChr->GetHookTick() < CFG(HookRegisterDelay))) Hooking = -1; } int HammeredBy = pChr->LastHammeredBy(); pChr->ClearLastHammeredBy(); if (Hooking >= 0) { CCharacter *pVic = CHAR(Hooking); if (pVic) { //bool SameTeam = pChr->GetPlayer()->GetTeam() == pVic->GetPlayer()->GetTeam(); m_aLastInteraction[Hooking] = /*SameTeam ? -1 : */ i; } } if (HammeredBy >= 0) { CCharacter *pHam = CHAR(HammeredBy); if (pHam) { //bool SameTeam = pChr->GetPlayer()->GetTeam() == pHam->GetPlayer()->GetTeam(); m_aLastInteraction[i] = /*SameTeam ? -1 : */ HammeredBy; if (/* !SameTeam &&*/ CFG(HammerFreeze) && pChr->GetFreezeTicks() <= 0) { pChr->Freeze(CFG(HammerFreeze) * TS, HammeredBy); m_aFrozenBy[i] = HammeredBy; //suppress kill event being generated } } else m_aLastInteraction[i] = -1; } } }
void CGameControllerOpenFNG::DoHookers() { for(int i = 0; i < MAX_CLIENTS; i++) { CCharacter *pChr = CHAR(i); if (!pChr) continue; int Hooking = pChr->GetHookedPlayer(); if (Hooking >= 0) { CCharacter *pVic = CHAR(Hooking); if (!pVic || (pVic->GetPlayer()->GetTeam() != pChr->GetPlayer()->GetTeam() && pChr->GetHookTick() < CFG(HookRegisterDelay))) Hooking = -1; } int HammeredBy = pChr->LastHammeredBy(); pChr->ClearLastHammeredBy(); if (Hooking >= 0) { CCharacter *pVic = CHAR(Hooking); if (pVic) { bool SameTeam = pChr->GetPlayer()->GetTeam() == pVic->GetPlayer()->GetTeam(); m_aLastInteraction[Hooking] = SameTeam ? -1 : i; } } /* CPlayer *pPlayer = TPLAYER(Hooking); if (pVic) { bool SameTeam = pChr->GetPlayer()->GetTeam() == pVic->GetPlayer()->GetTeam(); m_aLastInteraction[Hooking] = SameTeam ? -1 : i; if(pPlayer) { if (!SameTeam && CFG(HammerFreeze) && pVic->GetFreezeTicks() <= 0) { pVic->Freeze(CFG(HammerFreeze) * TS, i); m_aFrozenBy[Hooking] = i; //suppress kill event being generated } } } */ if (HammeredBy >= 0) { CCharacter *pHam = CHAR(HammeredBy); CPlayer *pPlayer = TPLAYER(HammeredBy); if (pHam) { bool SameTeam = pChr->GetPlayer()->GetTeam() == pHam->GetPlayer()->GetTeam(); m_aLastInteraction[i] = SameTeam ? -1 : HammeredBy; if(pPlayer) { if (!SameTeam && CFG(HammerFreeze) && pChr->GetFreezeTicks() <= 0 && pPlayer->m_HammerFreeze) { pChr->Freeze(CFG(HammerFreeze) * TS, HammeredBy); m_aFrozenBy[i] = HammeredBy; //suppress kill event being generated } } } else m_aLastInteraction[i] = -1; } } }
void CGameControllerOpenFNG::DoInteractions() { DoHookers(); for(int i = 0; i < MAX_CLIENTS; i++) { CCharacter *pChr = CHAR(i); if (!pChr) continue; int FrzTicks = pChr->GetFreezeTicks(); int Col = GameServer()->Collision()->GetCollisionAt(pChr->m_Pos.x, pChr->m_Pos.y); if (Col == TILE_SHRINE_ALL || Col == TILE_SHRINE_RED || Col == TILE_SHRINE_BLUE) { if (FrzTicks > 0 && m_aLastInteraction[i] < 0) pChr->Freeze(FrzTicks = 0); bool WasSacrificed = false; if (FrzTicks > 0) { int ShrineTeam = Col == TILE_SHRINE_RED ? TEAM_RED : Col == TILE_SHRINE_BLUE ? TEAM_BLUE : -1; HandleSacr(m_aLastInteraction[i], i, ShrineTeam); WasSacrificed = true; } pChr->Die(pChr->GetPlayer()->GetCID(), WEAPON_WORLD, WasSacrificed); } if (FrzTicks > 0) { if ((FrzTicks+1) % TS == 0) { int mask = -1; if (!CFG(MeltShowAll)) mask = (int)~m_aCltMask[1-(pChr->GetPlayer()->GetTeam()&1)]; GS->CreateDamageInd(pChr->m_Pos, 0, (FrzTicks+1) / TS, mask); if (CFG(ClickyMelt)) { mask = -1; if (CFG(ClickyMelt) == 1) mask = (int)m_aCltMask[1-(pChr->GetPlayer()->GetTeam()&1)]; GS->CreateSound(pChr->m_Pos, SOUND_WEAPON_NOAMMO, mask); } } if (FrzTicks == 1 && CFG(MeltSafeticks)) pChr->SetEmote(EMOTE_SURPRISE, TICK + CFG(MeltSafeticks) + 1); m_aMoltenBy[i] = -1; if (m_aFrozenBy[i] != -1) continue; int Killer = pChr->WasFrozenBy(); if (Killer < 0) //may happen then the gods are not pleased { m_aFrozenBy[i] = -1; continue; } m_aFrozenBy[i] = Killer; HandleFreeze(Killer, i); } else { m_aFrozenBy[i] = -1; int Melter = pChr->WasMoltenBy(); if (Melter < 0) m_aMoltenBy[i] = -1; if (Melter == m_aMoltenBy[i]) continue; m_aMoltenBy[i] = Melter; HandleMelt(Melter, i); } } }
void CCharacter::FireWeapon() { if(m_ReloadTimer != 0) return; DoWeaponSwitch(); vec2 Direction = normalize(vec2(m_LatestInput.m_TargetX, m_LatestInput.m_TargetY)); bool FullAuto = false; if(m_ActiveWeapon == WEAPON_GRENADE || m_ActiveWeapon == WEAPON_SHOTGUN || m_ActiveWeapon == WEAPON_RIFLE || (m_ActiveWeapon == WEAPON_HAMMER && g_Config.m_SvSuperHammer)) FullAuto = true; // check if we gonna fire bool WillFire = false; if(CountInput(m_LatestPrevInput.m_Fire, m_LatestInput.m_Fire).m_Presses) WillFire = true; if(FullAuto && (m_LatestInput.m_Fire&1) && m_aWeapons[m_ActiveWeapon].m_Ammo) WillFire = true; if (!g_Config.m_SvNinja && m_ActiveWeapon == WEAPON_NINJA) WillFire = false; if(!WillFire) return; // check for ammo if(!m_aWeapons[m_ActiveWeapon].m_Ammo) { // 125ms is a magical limit of how fast a human can click m_ReloadTimer = 125 * Server()->TickSpeed() / 1000; GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO); return; } vec2 ProjStartPos = m_Pos+Direction*m_ProximityRadius*0.75f; switch(m_ActiveWeapon) { case WEAPON_HAMMER: { // reset objects Hit m_NumObjectsHit = 0; GameServer()->CreateSound(m_Pos, SOUND_HAMMER_FIRE); CCharacter *apEnts[MAX_CLIENTS]; int Hits = 0; int Num = GameServer()->m_World.FindEntities(ProjStartPos, m_ProximityRadius*0.5f, (CEntity**)apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER); for (int i = 0; i < Num; ++i) { CCharacter *pTarget = apEnts[i]; if ((pTarget == this) || GameServer()->Collision()->IntersectLine(ProjStartPos, pTarget->m_Pos, NULL, NULL)) 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); else GameServer()->CreateHammerHit(ProjStartPos); vec2 Dir; if (length(pTarget->m_Pos - m_Pos) > 0.0f) Dir = normalize(pTarget->m_Pos - m_Pos); else Dir = vec2(0.f, -1.f); bool MeltHit = GameServer()->m_pController->IsTeamplay() && pTarget->GetPlayer()->GetTeam() == GetPlayer()->GetTeam() && pTarget->GetFreezeTicks() > 0; vec2 Force = (vec2(0.f, -1.f) + normalize(Dir + vec2(0.f, -1.1f)) * 10.0f); if (!MeltHit) { Force.x *= g_Config.m_SvHammerScaleX*0.01f; Force.y *= g_Config.m_SvHammerScaleY*0.01f; } else { Force.x *= g_Config.m_SvMeltHammerScaleX*0.01f; Force.y *= g_Config.m_SvMeltHammerScaleY*0.01f; } pTarget->TakeDamage(Force, g_pData->m_Weapons.m_Hammer.m_pBase->m_Damage, m_pPlayer->GetCID(), m_ActiveWeapon); Hits++; pTarget->m_HammeredBy = GetPlayer()->GetCID(); if (MeltHit) { pTarget->Freeze(pTarget->GetFreezeTicks() - g_Config.m_SvHammerMelt * Server()->TickSpeed()); if (pTarget->GetFreezeTicks() <= 0) { pTarget->m_MoltenBy = m_pPlayer->GetCID(); pTarget->m_MoltenAt = -1; // we don't want the unfreezability to take effect when being molten by hammer } } } // 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, m_pPlayer->GetCID(), ProjStartPos, Direction, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GunLifetime), 1, 0, 0, -1, WEAPON_GUN); // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); 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_GUN_FIRE); } break; case WEAPON_SHOTGUN: { int ShotSpread = 2; CMsgPacker Msg(NETMSGTYPE_SV_EXTRAPROJECTILE); Msg.AddInt(ShotSpread*2+1); for(int i = -ShotSpread; i <= ShotSpread; ++i) { 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); CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_SHOTGUN, m_pPlayer->GetCID(), ProjStartPos, vec2(cosf(a), sinf(a))*Speed, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_ShotgunLifetime), 1, 0, 0, -1, WEAPON_SHOTGUN); // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); 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); } break; case WEAPON_GRENADE: { CProjectile *pProj = new CProjectile(GameWorld(), WEAPON_GRENADE, m_pPlayer->GetCID(), ProjStartPos, Direction, (int)(Server()->TickSpeed()*GameServer()->Tuning()->m_GrenadeLifetime), 1, true, 0, SOUND_GRENADE_EXPLODE, WEAPON_GRENADE); // pack the Projectile and send it to the client Directly CNetObj_Projectile p; pProj->FillInfo(&p); 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); } break; case WEAPON_RIFLE: { new CLaser(GameWorld(), m_Pos, Direction, GameServer()->Tuning()->m_LaserReach, m_pPlayer->GetCID()); GameServer()->CreateSound(m_Pos, SOUND_RIFLE_FIRE); } break; case WEAPON_NINJA: { // reset Hit objects m_NumObjectsHit = 0; 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); } break; } m_AttackTick = Server()->Tick(); if (!g_Config.m_SvUnlimitedAmmo && m_aWeapons[m_ActiveWeapon].m_Ammo > 0) m_aWeapons[m_ActiveWeapon].m_Ammo--; if(!m_ReloadTimer) m_ReloadTimer = g_pData->m_Weapons.m_aId[m_ActiveWeapon].m_Firedelay * Server()->TickSpeed() / 1000; }