DDWORD Cat::ObjectMessageFn(HOBJECT hSender, DDWORD messageID, HMESSAGEREAD hRead) { switch(messageID) { case MID_DAMAGE: { CServerDE* pServerDE = GetServerDE(); if (!pServerDE) break; DVector vDir; pServerDE->ReadFromMessageVector(hRead, &vDir); DFLOAT fDamage = pServerDE->ReadFromMessageFloat(hRead); DamageType eType = (DamageType)pServerDE->ReadFromMessageByte(hRead); HOBJECT hHeHitMe = pServerDE->ReadFromMessageObject(hRead); if (eType == DT_SQUEAKY) { if (m_hstrSqueakedAtSound) { char* pSound = pServerDE->GetStringData(m_hstrSqueakedAtSound); if (pSound) PlaySoundFromObject(m_hObject, pSound, m_fSoundRadius, SOUNDPRIORITY_MISC_MEDIUM ); } // If we're supposed to trigger something, trigger it here if (m_hstrSqueakyTarget && m_hstrSqueakyMessage) { SendTriggerMsgToObjects(this, m_hstrSqueakyTarget, m_hstrSqueakyMessage); } } else { if (m_hstrDeathSound) { DVector vPos; pServerDE->GetObjectPos(m_hObject, &vPos); char* pSound = pServerDE->GetStringData(m_hstrDeathSound); if (pSound) PlaySoundFromPos(&vPos, pSound, m_fSoundRadius, SOUNDPRIORITY_MISC_MEDIUM ); } if (m_hstrDeathTriggerTarget && m_hstrDeathTriggerMessage) { SendTriggerMsgToObjects(this, m_hstrDeathTriggerTarget, m_hstrDeathTriggerMessage); } pServerDE->RemoveObject(m_hObject); } break; } default : break; } return InventoryItem::ObjectMessageFn(hSender, messageID, hRead); }
void GameStartPoint::SendTrigger() { if (!m_hstrTriggerTarget || !m_hstrTriggerMessage || !g_pServerDE) return; SendTriggerMsgToObjects(this, m_hstrTriggerTarget, m_hstrTriggerMessage); }
void PickupObject::PickedUp (HMESSAGEREAD hRead) { // get the override respawn time - if it's -1.0, use the default float nRespawn = g_pServerDE->ReadFromMessageFloat (hRead); if (nRespawn == -1.0f) nRespawn = m_fRespawnTime; // make the item invisible for the correct amount of time DDWORD dwFlags = g_pServerDE->GetObjectFlags(m_hObject); g_pServerDE->SetObjectFlags(m_hObject, dwFlags & ~FLAG_VISIBLE & ~FLAG_TOUCH_NOTIFY ); if( nRespawn <= 0.0f || g_pBloodServerShell->GetGameType() == GAMETYPE_SINGLE) g_pServerDE->RemoveObject( m_hObject ); else g_pServerDE->SetNextUpdate(m_hObject, (DFLOAT) nRespawn); // Let the world know what happened... if (m_szPickupSound) { DVector vPos; g_pServerDE->GetObjectPos( m_hObject, &vPos ); PlaySoundFromPos( &vPos, m_szPickupSound, 300.0f, SOUNDPRIORITY_MISC_HIGH); } // if we're supposed to trigger something, trigger it here if (m_hstrPickupTriggerTarget && m_hstrPickupTriggerMessage) { SendTriggerMsgToObjects(this, m_hstrPickupTriggerTarget, m_hstrPickupTriggerMessage); } }
void SoccerGoal::SendTrigger( ) { // Send the message if( m_hstrScoreTarget && m_hstrScoreMsg ) { SendTriggerMsgToObjects( this, m_hstrScoreTarget, m_hstrScoreMsg ); } }
void CinematicTrigger::SendReplyMessage(int nReply) { if (m_nCurMessage >= MAX_CT_MESSAGES) return; ILTCommon* pCommon = g_pLTServer->Common(); if (!pCommon) return; CString csTarget; CString csMsg; ConParse parse; char* pMsg = g_pLTServer->GetStringData(m_hstrRepliesTarget[m_nCurMessage]); if(!pMsg) return; parse.Init(pMsg); int i; for(i=0;i<nReply;i++) { if(pCommon->Parse(&parse) == LT_OK) { if(i == (nReply - 1)) { if (parse.m_nArgs > 0 && parse.m_Args[0]) { csTarget = parse.m_Args[0]; } break; } } } pMsg = g_pLTServer->GetStringData(m_hstrRepliesMsg[m_nCurMessage]); if(!pMsg) return; parse.Init(pMsg); for(i=0;i<nReply;i++) { if(pCommon->Parse(&parse) == LT_OK) { if(i == (nReply - 1)) { if (parse.m_nArgs > 0 && parse.m_Args[0]) { csMsg = parse.m_Args[0]; } break; } } } if (!csTarget.IsEmpty() && !csMsg.IsEmpty()) { SendTriggerMsgToObjects(this, (char *)(LPCSTR)csTarget, (char *)(LPCSTR)csMsg); } }
void CinematicTrigger::SendMessage() { if (m_nCurMessage < MAX_CT_MESSAGES) { if (m_hstrTargetName[m_nCurMessage] && m_hstrMessageName[m_nCurMessage]) { SendTriggerMsgToObjects(this, g_pLTServer->GetStringData( m_hstrTargetName[m_nCurMessage] ), g_pLTServer->GetStringData( m_hstrMessageName[m_nCurMessage] )); } } }
void WeaponItem::PickedUp(HMESSAGEREAD hRead) { // make the item invisible for the correct amount of time uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); g_pLTServer->SetObjectFlags(m_hObject, dwFlags & ~FLAG_VISIBLE & ~FLAG_TOUCH_NOTIFY); // Let the world know what happened... PlayPickedupSound(); // Clear our player obj, we no longer need this link... SetPlayerObj(LTNULL); // if we're supposed to trigger something, trigger it here if (m_hstrPickupTriggerTarget && m_hstrPickupTriggerMessage) { SendTriggerMsgToObjects(this, m_hstrPickupTriggerTarget, m_hstrPickupTriggerMessage); } // get the override respawn time - if it's -1.0, use the default LTFLOAT fRespawn = g_pLTServer->ReadFromMessageFloat (hRead); if (fRespawn == -1.0f) { fRespawn = m_fRespawnDelay; } fRespawn /= g_RespawnScaleTrack.GetFloat(1.0f); if (g_pGameServerShell->GetGameType() != SINGLE && g_WeaponsStay.GetFloat() > 0.0f && m_fRespawnDelay > 0.0f) { fRespawn = 0.1f; } if (fRespawn <= 0.0f || g_pGameServerShell->GetGameType() == SINGLE) { g_pLTServer->RemoveObject(m_hObject); } else { g_pLTServer->SetNextUpdate(m_hObject, fRespawn); } }
LTBOOL SendMixedTriggerMsgToObjects(LPBASECLASS pSender, HSTRING hName, HSTRING hMsg) { uint32 cMsgs = 0; char* aszMsgs[256]; ParseTriggerMsg(g_pLTServer->GetStringData(hMsg), aszMsgs, &cMsgs); LTBOOL bReturn = LTTRUE; for ( uint32 iMsg = 0 ; iMsg < cMsgs ; iMsg++ ) { bReturn &= SendTriggerMsgToObjects(pSender, g_pLTServer->GetStringData(hName), aszMsgs[iMsg]); } return bReturn; }
LTBOOL SendMixedTriggerMsgToObjects(LPBASECLASS pSender, const char* pName, const char* pMsg) { uint32 cMsgs = 0; char* aszMsgs[256]; ParseTriggerMsg(pMsg, aszMsgs, &cMsgs); LTBOOL bReturn = LTTRUE; for ( uint32 iMsg = 0 ; iMsg < cMsgs ; iMsg++ ) { bReturn &= SendTriggerMsgToObjects(pSender, pName, aszMsgs[iMsg]); } return bReturn; }
LTBOOL SendTriggerMsgToObjects(LPBASECLASS pSender, HSTRING hName, HSTRING hMsg) { if (!hMsg) return LTFALSE; char* pMsg = g_pLTServer->GetStringData(hMsg); // Process the message as a command if it is a valid command... if (g_pCmdMgr->IsValidCmd(pMsg)) { return g_pCmdMgr->Process(pMsg); } if (!hName) return LTFALSE; char* pName = g_pLTServer->GetStringData(hName); return SendTriggerMsgToObjects(pSender, pName, pMsg); }
bool Group::OnTrigger(HOBJECT hSender, const CParsedMsg &cMsg) { // Put the message back in a string char aMsgBuff[256]; cMsg.ReCreateMsg(aMsgBuff, sizeof(aMsgBuff), 0); const char* pName; for (uint32 i=0; i < m_nNumTargets; i++) { if (m_hstrObjectNames[i]) { pName = g_pLTServer->GetStringData(m_hstrObjectNames[i]); if (pName && pName[0]) { SendTriggerMsgToObjects(this, pName, aMsgBuff); } } } return true; }
void CDestructable::HandleDestruction() { CServerDE* pServerDE = BaseClass::GetServerDE(); if (!pServerDE) return; if (m_hstrDeathTriggerTarget) { LPBASECLASS pD = pServerDE->HandleToObject(m_hObject); SendTriggerMsgToObjects(pD, m_hstrDeathTriggerTarget, m_hstrDeathTriggerMessage); } // See if we need to spawn anything if (m_hstrSpawnObject) { DVector vPos; DRotation rRot; pServerDE->GetObjectPos(m_hObject, &vPos); pServerDE->GetObjectRotation(m_hObject, &rRot); SpawnObject(pServerDE->GetStringData(m_hstrSpawnObject), &vPos, &rRot, &m_vSpawnObjectVel); } }
void CinematicTrigger::HandleOff() { if (!m_bOn) return; for ( uint32 iWho = 0 ; iWho < MAX_CT_MESSAGES; iWho++ ) { if ( m_hstrWhoPlaysDialogue[iWho] ) { HOBJECT hWho; if ( LT_OK == FindNamedObject(m_hstrWhoPlaysDialogue[iWho], hWho) ) { if ( IsKindOf(hWho, "CAI") ) { CAI* pAI = (CAI*)g_pLTServer->HandleToObject(hWho); pAI->UnlinkCinematicTrigger(m_hObject); } } } } m_bOn = LTFALSE; // If we have a current speaker, make sure he is done talking... if (m_hCurSpeaker) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(m_hCurSpeaker); if (pChar) { pChar->StopDialogue(); } // Clear our speaker... g_pLTServer->BreakInterObjectLink(m_hObject, m_hCurSpeaker); m_hCurSpeaker = LTNULL; } // Clear out our last speaker if (m_hLastSpeaker) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(m_hLastSpeaker); if (pChar) { pChar->StopDialogue(TRUE); } g_pLTServer->BreakInterObjectLink(m_hObject, m_hLastSpeaker); m_hLastSpeaker = LTNULL; } // Send the clean up trigger message... if (m_hstrCleanUpTriggerTarget && m_hstrCleanUpTriggerMsg) { SendTriggerMsgToObjects(this, g_pLTServer->GetStringData( m_hstrCleanUpTriggerTarget ), g_pLTServer->GetStringData( m_hstrCleanUpTriggerMsg )); } // Turn off the camera... if (m_hCamera && !m_bLeaveCameraOn) { SendTriggerMsgToObject(this, m_hCamera, FALSE, "OFF"); } // Turn off the keyframer... if (m_hKeyFramer) { SendTriggerMsgToObject(this, m_hKeyFramer, FALSE, "OFF"); } SetNextUpdate(m_hObject, 0.0f); if (m_bOneTimeOnly) { // Can't get rid of object if we're leaving the camera on ;)... if (!m_hCamera || !m_bLeaveCameraOn) { g_pLTServer->RemoveObject(m_hObject); } } }
LTBOOL CinematicTrigger::Update() { if (!g_pLTServer) return LTFALSE; SetNextUpdate(m_hObject, 0.001f); LTBOOL bDialogueDone = !m_bDialogueDone ? !UpdateDialogue() : m_bDialogueDone; // If we created a camera and it is done end the cinematic... if (m_bCreateCamera) { if (!m_hCamera) { HandleOff(); } else { uint32 dwUsrFlags = g_pLTServer->GetObjectUserFlags(m_hCamera); if ( !(dwUsrFlags & USRFLG_CAMERA_LIVE) ) { HandleOff(); } } } // If the dialog is done and the keyframer is finished end the cinematic... if (bDialogueDone) { if (!m_bDialogueDone) { m_bDialogueDone = LTTRUE; // Send trigger... if (m_hstrDialogueDoneTarget && m_hstrDialogueDoneMsg) { SendTriggerMsgToObjects(this, g_pLTServer->GetStringData(m_hstrDialogueDoneTarget), g_pLTServer->GetStringData(m_hstrDialogueDoneMsg)); } } if (m_hKeyFramer) { KeyFramer* pKeyFramer = (KeyFramer*)g_pLTServer->HandleToObject(m_hKeyFramer); if (!pKeyFramer || pKeyFramer->m_bFinished) { HandleOff(); } } else { if (!m_hCamera) { HandleOff(); } } } return LTTRUE; }
LTBOOL CinematicTrigger::StartDialogue(int nDecision) { if(m_nCurMessage >= MAX_CT_MESSAGES) return LTFALSE; CString csDialogue; CString csTarget; CString csChar; uint8 byMood = 0; if(nDecision) { char* pMsg = g_pLTServer->GetStringData(m_hstrReplies[m_nCurMessage]); if(!pMsg) return FALSE; ILTCommon* pCommon = g_pLTServer->Common(); if (!pCommon) return FALSE; ConParse parse; parse.Init(pMsg); for(int i=0;i<nDecision;i++) { if(pCommon->Parse(&parse) == LT_OK) { if (parse.m_nArgs < 2) { if (parse.m_nArgs < 1 || stricmp(parse.m_Args[0], "NONE") != 0) { g_pLTServer->CPrint("Cinematic Trigger - ERROR - Not enough replies for the amount of decisions!"); TRACE("Cinematic Trigger - ERROR - Not enough replies for the amount of decisions!\n"); return FALSE; } } else if(i == (nDecision - 1)) { csTarget = parse.m_Args[0]; if(csTarget.Compare("Cinematic") == 0) { //HandleOff(); - Should be done by reply message? // Force the dialogue to be done... m_nCurMessage = MAX_CT_MESSAGES; // We have another cinematic to play, turn it on... SendTriggerMsgToObjects(this, parse.m_Args[1], "ON"); return FALSE; } else { // Look at the second argument to determine if we have a // character override if((parse.m_Args[1][0] < '0') && (parse.m_Args[1][0] > '9')) { // We have a character override csChar = parse.m_Args[1]; csDialogue = parse.m_Args[2]; // Check for a mood if(parse.m_nArgs == 4) { // char charoverride id mood byMood = atoi(parse.m_Args[3]); } } else { // We don't have a character override csDialogue = parse.m_Args[1]; // check for a mood if(parse.m_nArgs == 3) { // char id mood byMood = atoi(parse.m_Args[2]); } } } } } } } else { // Send the message here SendMessage(); // Check for an initial message if (m_nCurMessage == 0) { if (m_hstrDialogueStartTarget && m_hstrDialogueStartMsg) { SendTriggerMsgToObjects(this, g_pLTServer->GetStringData(m_hstrDialogueStartTarget), g_pLTServer->GetStringData(m_hstrDialogueStartMsg)); } } csDialogue = g_pLTServer->GetStringData(m_hstrDialogue[m_nCurMessage]); csTarget = g_pLTServer->GetStringData(m_hstrWhoPlaysDialogue[m_nCurMessage]); } if (csDialogue.IsEmpty()) { // Make sure the reply messages are sent, even if we aren't going to // do any dialogue... if (nDecision) { SendReplyMessage(nDecision); } return LTFALSE; } const char *szCharOverride = NULL; if(csChar.IsEmpty()) { int nSpace = csTarget.Find(' '); if(nSpace != -1) { // There is a space in the name, therefore we have a character override csChar = csTarget.Right(csTarget.GetLength()-nSpace-1); csTarget = csTarget.Left(nSpace); if(!csChar.IsEmpty()) szCharOverride = csChar; } } else { szCharOverride = csChar; } HOBJECT hObj = !csTarget.IsEmpty() ? PlayedBy((char *)(LPCSTR)csTarget) : LTNULL; if (hObj) { CCharacter* pChar = (CCharacter*)g_pLTServer->HandleToObject(hObj); if (pChar) { char *szDecisions = NULL; if (!nDecision && m_hstrDecisions[m_nCurMessage]) { szDecisions = g_pLTServer->GetStringData(m_hstrDecisions[m_nCurMessage]); } // See if there's a windowed message next int nNext = m_nCurMessage + 1; //BOOL bStayOpen = (szDecisions || ((nNext < MAX_CT_MESSAGES) && m_hstrDialogue[nNext] && m_bWindow[nNext] && (m_fDelay[nNext] == 0.0f))); //BOOL bWindow = m_bWindow[m_nCurMessage]; BOOL bStayOpen = LTFALSE; BOOL bWindow = (BOOL)szDecisions; pChar->PlayDialogue((char *)(LPCSTR)csDialogue,this,bWindow,bStayOpen,szCharOverride,szDecisions,byMood); SetupLinks(hObj); return LTTRUE; } } return LTFALSE; }
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); } } } }
void Trigger::Activate() { CServerDE* pServerDE = GetServerDE(); if (!pServerDE) return; // Make us wait a bit before we can be triggered again... if (m_bTimedTrigger) { pServerDE->SetNextUpdate(m_hObject, UPDATE_DELTA); pServerDE->SetDeactivationTime(m_hObject, 0.0f); } else { pServerDE->SetNextUpdate(m_hObject, m_fTriggerDelay); pServerDE->SetDeactivationTime(m_hObject, 0.0f); } // If this is a counter trigger, determine if we can activate or not... if (++m_nCurrentActivation < m_nActivationCount) { return; } else { m_nCurrentActivation = 0; } if (m_hstrActivationSound) { char* pSound = pServerDE->GetStringData(m_hstrActivationSound); if (pSound && pSound[0] != '\0') { PlaySoundFromObject(m_hObject, pSound, m_fSoundRadius, SOUNDPRIORITY_MISC_HIGH); } } DBOOL bTriggerMsg1 = DTRUE; DBOOL bTriggerMsg2 = DTRUE; if (m_bWeightedTrigger) { bTriggerMsg1 = (GetRandom(0.0f, 1.0f) < m_fMessage1Weight ? DTRUE : DFALSE); bTriggerMsg2 = !bTriggerMsg1; } for (int i=0; i < MAX_NUM_MESSAGES; i++) { DBOOL bOkayToSend = DTRUE; if (i == 0 && !bTriggerMsg1) bOkayToSend = DFALSE; else if (i == 1 && !bTriggerMsg2) bOkayToSend = DFALSE; if (bOkayToSend && m_hstrTargetName[i] && m_hstrMessageName[i]) { SendTriggerMsgToObjects(this, m_hstrTargetName[i], m_hstrMessageName[i]); } } if (m_bTouchNotifyActivation && m_hTouchObject && m_bTriggerTouch && m_hstrMessageTouch) { SendTriggerMsgToObject(this, m_hTouchObject, m_hstrMessageTouch); m_bTouchNotifyActivation = DFALSE; m_hTouchObject = DNULL; } }
CScanner::DetectState CScanner::UpdateDetect() { CCharacter* pChar = g_pCharacterMgr->LookForEnemy(this); CDeathScene* pScene = g_pCharacterMgr->LookForDeathScene(this); if (pChar || pScene) { // Set the focus timer if it hasn't been set...(i.e., the // first time we see a "situation")... LTBOOL bFocus = !!(GetFocusTime() > 0.0f); if (bFocus && !m_FocusTimer.GetDuration()) { m_FocusTimer.Start(GetFocusTime()); } else if (!bFocus || m_FocusTimer.Stopped()) { // Only process detection once (unless it is reset // someplace else...)... if (m_bCanProcessDetection) { if (pChar) { SetLastDetectedEnemy(pChar->m_hObject); } else if (pScene) { SetLastDetectedDeathPos(pScene->GetPosition()); } SendTriggerMsgToObjects(this, m_hstrSpotTarget, m_hstrSpotMessage); m_bCanProcessDetection = LTFALSE; } return DS_DETECTED; } return DS_FOCUSING; } else { // If the focus timer has stopped (i.e., we tried to focus on // a character but he moved before we detected him, stop the // timer (which will reset the duration)... if (m_FocusTimer.Stopped()) { m_FocusTimer.Stop(); } else { return DS_FOCUSING; } } return DS_CLEAR; }