void GearItem::PickedUp(ILTMessage_Read *pMsg) { // Did we really pick it up? bool bPickedUp = (pMsg ? pMsg->Readbool() : true); // If we were touched by a player, our m_hPlayerObj data member will be // set. Send a message to that player's client letting it know that an // item has been picked up... if (m_hPlayerObj) { CPlayerObj* pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(m_hPlayerObj); if (pPlayer && !pPlayer->IsDead()) { HCLIENT hClient = pPlayer->GetClient(); if (hClient) { CAutoMessage cMsg; cMsg.Writeuint8(MID_GEAR_PICKEDUP); cMsg.Writeuint8((uint8)m_nGearId); cMsg.Writebool(bPickedUp); g_pLTServer->SendToClient(cMsg.Read(), hClient, MESSAGE_GUARANTEED); } } } if (bPickedUp) { PickupItem::PickedUp(pMsg); if( m_bRespawn ) { GEAR const *pGear = g_pWeaponMgr->GetGear( m_nGearId ); if( !pGear ) return; // Change the skins and renderstyles to the waiting to respawn files... ObjectCreateStruct ocs; pGear->blrRespawnWaitSkins.CopyList( 0, ocs.m_SkinNames[0], MAX_CS_FILENAME_LEN + 1 ); pGear->blrRespawnWaitRenderStyles.CopyList( 0, ocs.m_RenderStyleNames[0], MAX_CS_FILENAME_LEN + 1 ); if( pGear->blrRespawnWaitRenderStyles.GetNumItems() < 1 ) LTStrCpy( ocs.m_RenderStyleNames[0], s_szDefaultRS, ARRAY_LEN( s_szDefaultRS )); g_pCommonLT->SetObjectFilenames( m_hObject, &ocs ); // Stop playing PowerupFX and play RespawnWaitFX... SetClientFX( pGear->szRespawnWaitFX ); // Set our visibility... g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, pGear->bRespawnWaitVisible ? FLAG_VISIBLE : 0, FLAG_VISIBLE ); g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags2, pGear->bRespawnWaitTranslucent ? FLAG2_FORCETRANSLUCENT : 0, FLAG2_FORCETRANSLUCENT ); } } }
LTBOOL PlayerTrigger::Activate() { if (g_pGameServerShell->IsPaused()) { return LTFALSE; } // Find all the objects within the trigger... LTVector vDims; g_pPhysicsLT->GetObjectDims( m_hObject, &vDims ); LTVector vPos; g_pLTServer->GetObjectPos( m_hObject, &vPos ); LTVector vMin = vPos - vDims; LTVector vMax = vPos + vDims; ObjectList *pObjList = g_pLTServer->GetBoxIntersecters( &vMin, &vMax ); if( !pObjList ) return LTFALSE; // Count the number of players in the trigger and activate only if // ALL players in the game are within the trigger... HOBJECT hObj; uint32 nPlayersInGame = CPlayerObj::GetNumberPlayersWithClients( ); // Don't trigger if there are no players in the game. if( nPlayersInGame == 0 ) return LTFALSE; uint32 nPlayersInTrigger = 0; ObjectLink *pLink = pObjList->m_pFirstLink; while( pLink ) { hObj = pLink->m_hObject; CPlayerObj* pPlayerObj = dynamic_cast< CPlayerObj* >( g_pLTServer->HandleToObject( hObj )); // Only count live players with loaded clients. if( pPlayerObj && !pPlayerObj->IsDead( ) && pPlayerObj->IsClientLoaded( )) { ++nPlayersInTrigger; } pLink = pLink->m_pNext; } g_pLTServer->RelinquishList( pObjList ); if( nPlayersInTrigger != nPlayersInGame ) return LTFALSE; // Ok! All the players are acounted for. // Let the base Trigger object activate. return Trigger::Activate(); }
bool PickupItem::OnTrigger(HOBJECT hSender, const CParsedMsg &cMsg) { static CParsedMsg::CToken s_cTok_Activate("ACTIVATE"); static CParsedMsg::CToken s_cTok_Team( "TEAM" ); if( cMsg.GetArg(0) == s_cTok_Activate ) { // Can't activate before we've respawned. if( m_bWasPickedUp ) return true; // If the object is dead, it can't pick up stuff... if (IsPlayer(hSender)) { CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hSender); if (!pPlayer || pPlayer->IsDead()) return true; SetPlayerObj(hSender); ObjectTouch(hSender); } else { SetPlayerObj(LTNULL); return true; } } else if (cMsg.GetArg(0) == s_cTok_Team) { if( cMsg.GetArgCount( ) > 1 ) { uint32 nTeamId = atoi( cMsg.GetArg( 1 )); if( nTeamId < MAX_TEAMS ) { SetTeamId( nTeamId ); } else { SetTeamId( INVALID_TEAM ); } return true; } } else return GameBase::OnTrigger(hSender, cMsg); return true; }
void GearItem::ObjectTouch(HOBJECT hObject) { if (!hObject) return; // If we hit non-player objects, just ignore them... if (IsPlayer(hObject)) { CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hObject); if (pPlayer && !pPlayer->IsDead()) { HMESSAGEWRITE hMessage = g_pLTServer->StartMessageToObject(this, hObject, MID_ADDGEAR); g_pLTServer->WriteToMessageByte(hMessage, m_nGearId); g_pLTServer->EndMessage(hMessage); } } }
void ModItem::ObjectTouch(HOBJECT hObject, bool bForcePickup/*=false*/) { if (!hObject) return; // If we hit non-player objects, just ignore them... if (IsPlayer(hObject)) { CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hObject); if (pPlayer && !pPlayer->IsDead()) { SetPlayerObj(hObject); CAutoMessage cMsg; cMsg.Writeuint32(MID_ADDMOD); cMsg.Writeuint8((uint8)m_nModId); g_pLTServer->SendToObject(cMsg.Read(), m_hObject, hObject, MESSAGE_GUARANTEED); } } }
void GearItem::PickedUp(HMESSAGEREAD hRead) { // If we were touched by a player, our m_hPlayerObj data member will be // set. Send a message to that player's client letting it know that an // item has been picked up... if (m_hPlayerObj) { CPlayerObj* pPlayer = (CPlayerObj*) g_pLTServer->HandleToObject(m_hPlayerObj); if (pPlayer && !pPlayer->IsDead()) { HCLIENT hClient = pPlayer->GetClient(); if (hClient) { HMESSAGEWRITE hWrite = g_pLTServer->StartMessage(hClient, MID_GEAR_PICKEDUP); g_pLTServer->WriteToMessageByte(hWrite, m_nGearId); g_pLTServer->EndMessage(hWrite); } } } PickupItem::PickedUp(hRead); }
uint32 PickupItem::EngineMessageFn(uint32 messageID, void *pData, LTFLOAT fData) { switch(messageID) { case MID_UPDATE: { Update(); } break; case MID_TOUCHNOTIFY: { if( !m_bTouchPickup ) break; HOBJECT hObj = (HOBJECT)pData; // If this is a character hit box, use its object... CCharacterHitBox* pHitBox = LTNULL; if (IsCharacterHitBox(hObj)) { pHitBox = (CCharacterHitBox*)g_pLTServer->HandleToObject(hObj); if (pHitBox) { hObj = pHitBox->GetModelObject(); } } // If the object is dead, it can't pick up stuff... if (IsPlayer(hObj)) { CPlayerObj* pPlayer = (CPlayerObj*)g_pLTServer->HandleToObject(hObj); if (!pPlayer || pPlayer->IsDead()) break; SetPlayerObj(hObj); } else { SetPlayerObj(LTNULL); break; } ObjectTouch(hObj); } break; case MID_PRECREATE: { ObjectCreateStruct* pInfo = (ObjectCreateStruct*)pData; if (fData == PRECREATE_WORLDFILE) { ReadProp(pInfo); } else if (fData == PRECREATE_STRINGPROP) { ReadProp(pInfo); // Show ourself... pInfo->m_Flags |= FLAG_VISIBLE; } PostPropRead(pInfo); } break; case MID_INITIALUPDATE: { if (fData != INITIALUPDATE_SAVEGAME) { InitialUpdate(); } } break; case MID_SAVEOBJECT: { Save((ILTMessage_Write*)pData, (uint32)fData); } break; case MID_LOADOBJECT: { Load((ILTMessage_Read*)pData, (uint32)fData); uint32 dwRet = GameBase::EngineMessageFn(messageID, pData, fData); // We need to reset our sfx message since values // could have changed across save versions. CreateSpecialFX( ); return dwRet; } break; default : break; } return GameBase::EngineMessageFn(messageID, pData, fData); }
bool DoomsDayDevice::DamageVictims( bool& bAllDead ) { TRACE( "DoomsDayDevice::DamageVictims\n" ); char szDamageType[256]; if( !g_pServerButeMgr->GetDoomsDayDeviceDamageType( szDamageType, ARRAY_LEN( szDamageType ))) { return false; } DamageStruct damage; damage.eType = StringToDamageType( szDamageType ); damage.fDamage = g_pServerButeMgr->GetDoomsDayDeviceDamageAmount( ); damage.hDamager = m_hObject; damage.fDuration = 30.0f; // Initialize the status to all the players being dead. bAllDead = true; // Find all the victim teams and kill them. uint8 nNumTeams = CTeamMgr::Instance( ).GetNumTeams( ); for( uint8 nTeam = 0; nTeam < nNumTeams; nTeam++ ) { // Skip the activating team. if( nTeam == m_nOwningTeamID ) continue; CTeam* pTeam = CTeamMgr::Instance( ).GetTeam( nTeam ); if( !pTeam ) { ASSERT( !"DoomsDayDevice::DamageVictims: Invalid team." ); continue; } // Iterate over each player on the team and kill him. PlayerIDSet const& players = pTeam->GetPlayerIDSet( ); PlayerIDSet::const_iterator iter = players.begin( ); while( iter != players.end( )) { uint32 nClientId = *iter; iter++; HCLIENT hClient = g_pLTServer->GetClientHandle( nClientId ); if( !hClient ) continue; CPlayerObj* pTeamPlayer = ( CPlayerObj* )g_pLTServer->GetClientUserData( hClient ); if( !pTeamPlayer ) continue; // Skip if already dead. if( pTeamPlayer->IsDead( )) continue; // This player is still alive, so update the status variable. bAllDead = false; // Do the damage. damage.DoDamage( this, pTeamPlayer->m_hObject ); } } return true; }
void CDestructable::HandleDamage(HOBJECT hSender, HMESSAGEREAD hRead) { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return; DVector vDir,vPos; pServerDE->ReadFromMessageVector(hRead, &vDir); DFLOAT fDamage = pServerDE->ReadFromMessageFloat(hRead); DBYTE nDamageType = pServerDE->ReadFromMessageByte(hRead); HOBJECT hWhoHit = pServerDE->ReadFromMessageObject(hRead); pServerDE->ReadFromMessageVector(hRead, &vPos); // char buf[50]; DFLOAT fOldHitPoints = m_fHitPoints; fDamage = fDamage * m_fResistance; // Just return if we can't take damage if (m_bGodMode || (m_bTriggerOnly && nDamageType != DAMAGE_TYPE_DEATH) || fDamage < 0) { return; } if (!IsPlayerToPlayerDamageOk(hSender, hWhoHit)) { return; } // If instant death, don't bother calculating stuff.. if( m_bDestructable && nDamageType == DAMAGE_TYPE_DEATH) { m_fArmorPoints = 0; m_fHitPoints = 0; m_fDeathHitPoints = 0; m_fLastDamagePercent = 100.0f; m_fLastDamageAmount = (DFLOAT)m_fMaxHitPoints; nDamageType &= 0x0f; // Mask off the damage type flags m_nLastDamageType = nDamageType; } else { // Special pre-damage base character modifiers if (IsAICharacter(m_hObject)) { m_nNodeHit = CalculateHitLimb(vDir,vPos,fDamage); if(m_nNodeHit == -1 && !(nDamageType & DAMAGE_TYPE_NORMAL)) m_nNodeHit = SetProperNode(pServerDE->IntRandom(0,NUM_ALL_NODES - 3)); else if(m_nNodeHit >= 0) m_nNodeHit = SetProperNode(m_nNodeHit); else return; //Compute one side got hit for recoils DVector vU, vR, vF, vTmpDir; DRotation rRot; pServerDE->GetObjectRotation(m_hObject, &rRot); pServerDE->GetRotationVectors(&rRot, &vU, &vR, &vF); VEC_COPY(vTmpDir, vDir); VEC_MULSCALAR(vTmpDir,vTmpDir,-1.0f); DFLOAT fAmount = (DFLOAT) atan2(vTmpDir.x, vTmpDir.z); DFLOAT fAmount2 = (DFLOAT) atan2(vF.x, vF.z); if(fAmount < 0.0f) fAmount = (MATH_PI*2) + fAmount; if(fAmount2 < 0.0f) fAmount2 = (MATH_PI*2) + fAmount2; DFLOAT fAngle = fAmount2 - fAmount; if(fAngle <= MATH_PI/2 || fAngle >= 3*MATH_PI/2) //Hit the front { m_nSideHit = 0; } else //Hit the back { m_nSideHit = 6; } if (m_hLastDamager) pServerDE->BreakInterObjectLink(m_hObject, m_hLastDamager); m_hLastDamager = hWhoHit; if(m_hLastDamager) pServerDE->CreateInterObjectLink(m_hObject, m_hLastDamager); if(m_nNodeHit == NODE_NECK) { AI_Mgr* pAI = (AI_Mgr*)pServerDE->HandleToObject(m_hObject); if(pAI->m_bCabal || pServerDE->IsKindOf(pServerDE->GetObjectClass(m_hObject), pServerDE->GetClass("SoulDrudge"))) m_fHitPoints = 0; fDamage *= 1.5f; } else if(m_nNodeHit == NODE_TORSO) { fDamage *= 1.0f; } else { fDamage *= 0.5f; } } if (IsBaseCharacter(m_hObject)) { CBaseCharacter *pOwner = (CBaseCharacter*)pServerDE->HandleToObject(m_hObject); // if (pOwner->IsItemActive(SPELL_STONE)) // return; // If Nigh-invulnerability powerup in effect.. if (m_bNighInvulnerable) fDamage = fDamage * 0.05f; // Shield absorbs the damage as Focus ammo use /* if (nDamageType != DAMAGE_TYPE_DEATH && pOwner->IsItemActive(SPELL_SHIELD)) { DFLOAT fFocusAmmo = pOwner->GetInventoryMgr()->GetAmmoCount(AMMO_FOCUS); fFocusAmmo -= fDamage; if (fFocusAmmo < 0.0f) { fDamage = -fFocusAmmo; fFocusAmmo = 0.0f; } else { fDamage = 0.0f; } pOwner->GetInventoryMgr()->SetAmmoCount(AMMO_FOCUS, fFocusAmmo); } */ // Reflection reflects damage back to the sender, and absorbs // twice the damage in focus ammo /* if (pOwner->IsItemActive(SPELL_REFLECTION) && !(nDamageType & DAMAGE_FLAG_AREAEFFECT)) { DFLOAT fFocusAmmo = pOwner->GetInventoryMgr()->GetAmmoCount(AMMO_FOCUS); fFocusAmmo -= fDamage * 2.0f; if (fFocusAmmo < 0.0f) { fDamage = -fFocusAmmo / 2.0f; fFocusAmmo = 0.0f; } else { fDamage = 0.0f; } pOwner->GetInventoryMgr()->SetAmmoCount(AMMO_FOCUS, fFocusAmmo); } */ } // If single player, don't let the player apply damage to himself. if (m_bApplyDamagePhysics && !(g_pBloodServerShell->GetGameType() == GAMETYPE_SINGLE && (m_hObject == hWhoHit) && IsPlayer(m_hObject))) ApplyDamagePhysics(fDamage, &vDir); // Can't damage if already dead... if( m_bDestructable && m_bDead ) return; if( m_bDestructable && m_fArmorPoints > 0.0 && nDamageType != DAMAGE_TYPE_SUFFOCATE ) { DFLOAT fAbsorb = 0.0f; if (m_fArmorPoints <= 25.0f) fAbsorb = fDamage * 0.3f; else if (m_fArmorPoints <= 50.0f) fAbsorb = fDamage * 0.5f; else if (m_fArmorPoints <= 100.0f) fAbsorb = fDamage * 0.7f; else if (m_fArmorPoints <= 150.0f) fAbsorb = fDamage * 0.8f; else fAbsorb = fDamage * 0.9f; if (!m_bGodMode) { m_fArmorPoints -= fAbsorb; if (m_fArmorPoints < 0.0f) { fAbsorb += m_fArmorPoints; m_fArmorPoints = 0.0f; } fDamage -= fAbsorb; } } if (fDamage < 0.0f) fDamage = 0.0f; // just to be sure :) // Save damage type so entity will know how to react nDamageType &= 0x0f; // Mask off the damage type flags if (fDamage) m_nLastDamageType = nDamageType; if( m_bDestructable ) { m_fHitPoints -= fDamage; m_fDeathHitPoints -= fDamage; } } // 01/13/98 How much damage was done (percentage of max hit points) m_fLastDamagePercent += (DFLOAT)fDamage/(DFLOAT)GetMaxHitPoints(); m_fLastDamageAmount += fDamage; VEC_COPY(m_vLastDamageDirection, vDir); // Set pSender if sender is a player CPlayerObj* pSender = DNULL; if( m_bDestructable ) { if(hWhoHit) if(pServerDE->IsKindOf(pServerDE->GetObjectClass(hWhoHit), pServerDE->GetClass("CPlayerObj"))) pSender = (CPlayerObj*)pServerDE->HandleToObject(hWhoHit); // If it was hurt with a leech weapon, then add the damage done back to playerobj if(pSender && pServerDE->IsKindOf(pServerDE->GetObjectClass(m_hObject), pServerDE->GetClass("CBaseCharacter"))) { if(nDamageType == DAMAGE_TYPE_LEECH) { if (!pSender->IsDead() && !pSender->IsInSlowDeath()) { pSender->GetDestructable()->Heal(fDamage / 10.0f); } } } } // m_fHitPoints = 1; if( m_bDestructable && m_fHitPoints <= 0 ) { m_bDead = DTRUE; m_fHitPoints = 0; HandleDestruction(); m_hWhoKilledMeLast = hWhoHit; // If its a PlayerObj then Increase the Kills /* if(pSender && pServerDE->IsKindOf(pServerDE->GetObjectClass(m_hObject), pServerDE->GetClass("CBaseCharacter"))) { // If it was killed with a melee weapon, then add the damage done back to playerobj if(nDamageType == DAMAGE_TYPE_LEECH) { pSender->GetDestructable()->Heal(fDamage / 5.0f); pSender->AddMeleeKill(); DFLOAT fIncrease = 0.0f; int nKills = pSender->GetMeleeKills(); if (nKills > 0) { // Increase Damage by 5% for every kill fIncrease = (DFLOAT)nKills * .05f; // Max Increase 200% if (fIncrease > 2.0f) fIncrease = 2.0f; } // If the Increase is greater than 50% then add back some of the damage to player if (fIncrease > 0.5f) { // Add back damage to playerobj DFLOAT fAddHits = fDamage * (fIncrease/2.0f); pSender->GetDestructable()->Heal(fAddHits); // Need to Glow the player Sword... // Set Glow on the Melee Weapon } } }*/ } // If this is supposed to send a damage trigger, send it now.. if( m_bDestructable && m_hstrDamageTriggerTarget && m_hstrDamageTriggerMessage ) { LPBASECLASS pD = pServerDE->HandleToObject(m_hObject); SendTriggerMsgToObjects(pD, m_hstrDamageTriggerTarget, m_hstrDamageTriggerMessage); } // If player did this damage and has soul stealing binding.. if( m_bDestructable && fOldHitPoints != m_fHitPoints && m_hObject != hWhoHit) { // Make sure it's a player if(pSender) { DFLOAT fHeal; if (pSender->HasSoulStealingBinding() && (fHeal = (fOldHitPoints - m_fHitPoints) / 10.0f)) { pSender->GetDestructable()->Heal(fHeal); } } } }