#include "precompiled.h" #pragma hdrstop #include "Game_local.h" #include "../prey/ai_speech.h" #include "../prey/ai_reaction.h" // HUMANHEAD additions to the idEntity class //HUMANHEAD const idEventDef EV_SetSkinByName( "setSkin", "s" ); const idEventDef EV_Deactivate( "deactivate" ); const idEventDef EV_GlobalBeginState( "" ); const idEventDef EV_GlobalTicker( "" ); const idEventDef EV_GlobalEndState( "" ); const idEventDef EV_GlobalDeactivate( "" ); const idEventDef EV_GlobalActivate( "", "e" ); const idEventDef EV_DeadBeginState( "" ); const idEventDef EV_DeadTicker( "" ); const idEventDef EV_DeadEndState( "" ); const idEventDef EV_MoveToJoint( "moveToJoint", "es" ); const idEventDef EV_MoveToJointWeighted( "moveToJointWeighted", "esv" ); const idEventDef EV_MoveJointToJoint( "moveJointToJoint", "ses" ); const idEventDef EV_MoveJointToJointOffset( "moveJointToJointOffset", "sesv" ); const idEventDef EV_SpawnDebris("spawnDebris", "s"); const idEventDef EV_DamageEntity( "", "es" ); const idEventDef EV_DelayDamageEntity( "delayDamageEntity", "esf" ); const idEventDef EV_Dispose( "dispose" ); const idEventDef EV_ResetGravity( "", NULL ); const idEventDef EV_LoadReactions(""); const idEventDef EV_SetDeformation("setDeformation", "dff" ); const idEventDef EV_Broadcast_AssignFx( "", "e" ); const idEventDef EV_Broadcast_AppendFxToList( "", "e" ); const idEventDef EV_SetFloatKey( "setFloatKey", "sf" ); const idEventDef EV_SetVectorKey( "setVectorKey", "sv" ); const idEventDef EV_SetEntityKey( "setEntityKey", "se" ); const idEventDef EV_PlayerCanSee( "playerCanSee", NULL, 'd' ); const idEventDef EV_SetPortalCollision( "setPortalCollision", "d" ); const idEventDef EV_KillBox( "killbox", NULL ); // pdm //HUMANHEAD END /* ================ idEntity::InitCoreStateInfo HUMANHEAD: aob - state init code ================ */ void idEntity::InitCoreStateInfo() { } /* ================ idEntity::Ticker HUMANHEAD pdm ================ */ void idEntity::Ticker( void ) { // Overridable function for conditionally running logic each frame, seperate from // whether you want to run physics, animation, rendering, and sound } /* ================ idEntity::RestoreGUI HUMANHEAD: aob ================ */ void idEntity::RestoreGUI( const char* guiKey, idUserInterface** gui ) { if( guiKey && guiKey[0] && gui ) { AddRenderGui( spawnArgs.GetString(guiKey), gui, &spawnArgs ); } } /* ================ idEntity::RestoreGUIs HUMANHEAD: aob ================ */ void idEntity::RestoreGUIs() { RestoreGUI( "gui", &renderEntity.gui[0] ); for( int ix = 1; ix < MAX_RENDERENTITY_GUI; ix++ ) { RestoreGUI( va("gui%d", ix+1), &renderEntity.gui[ix] ); } } /* ================ idEntity::SetSkinByName HUMANHEAD: aob ================ */ void idEntity::SetSkinByName( const char *skinname ) { SetSkin( (!skinname || !skinname[0]) ? NULL : declManager->FindSkin(skinname) ); } //========================================================================= // // idEntity::Portalled // // HUMANHEAD // This entity was just portalled //========================================================================= void idEntity::Portalled(idEntity *portal) { // Scan for any shuttles that are tractoring me and tell it to let go in that case for( idEntity *ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) { if ( ent->IsType( hhShuttle::Type ) ) { hhShuttle *shuttle = static_cast(ent); if (shuttle->GetTractorTarget() == this) { shuttle->ReleaseTractorTarget(); } } } return; } /* ===================== idEntity::CheckPortal Checks if a portal can teleport this entity HUMANHEAD: cjr ===================== */ bool idEntity::CheckPortal( const idEntity *other, int contentMask ) { return false; } bool idEntity::CheckPortal( const idClipModel *mdl, int contentMask ) { return false; } void idEntity::CollideWithPortal( const idEntity *other ) { // HUMANHEAD CJR PCF 04/26/06 } void idEntity::CollideWithPortal( const idClipModel *mdl ) { // HUMANHEAD CJR PCF 04/26/06 } /* ================ idEntity:MoveToJoint HUMANHEAD nla ================ */ void idEntity::MoveToJoint( idEntity *master, const char *bonename ) { idVec3 weight(1, 1, 1); MoveToJointWeighted( master, bonename, weight); } /* ================ idEntity::MoveToJointWeighted master - The owner of the bone to move to bonename - The name of the bone to move to weight - Vector giving the amount of influence the bone will have over the new location. (1, 1, 0) would move the player 100% in X and Y, but none in Z. (.5, 0, 1) would move the player 1/2 way to the bone in x, none in y, and 100% in z HUMANHEAD nla ================ */ void idEntity::MoveToJointWeighted( idEntity *master, const char *bonename, idVec3 &weight ) { jointHandle_t jointnum; idVec3 boneOrigin; idMat3 boneAxis; idVec3 newOrigin; if ( master == this ) { gameLocal.Error( "Tried to move an object to itself." ); return; } // Make sure what we are moving to has joints! if ( !master->GetAnimator() ) { gameLocal.Error( "Tried to move %s (%s) to a joint on non animated entity %s (%s)\n", name.c_str(), spawnArgs.GetString( "spawnclass" ), master->name.c_str(), master->spawnArgs.GetString( "spawnclass" ) ); } jointnum = master->GetAnimator()->GetJointHandle( bonename ); if ( jointnum == INVALID_JOINT ) { gameLocal.Error( "Bone '%s' not found.", bonename ); return; } master->GetAnimator()->GetJointTransform( jointnum, gameLocal.time, boneOrigin, boneAxis ); //gameLocal.Printf("Moving origin from (%s) %s to ", boneOrigin.ToString(), GetPhysics()->GetOrigin().ToString() ); // boneOrigin is already rotated by the master axis newOrigin = boneOrigin * master->GetAxis() + master->GetOrigin(); idVec3 myOrigin = GetOrigin(); newOrigin.x = newOrigin.x * weight.x + myOrigin.x * ( 1 - weight.x ); newOrigin.y = newOrigin.y * weight.y + myOrigin.y * ( 1 - weight.y ); newOrigin.z = newOrigin.z * weight.z + myOrigin.z * ( 1 - weight.z ); SetOrigin( newOrigin ); //gameLocal.Printf("%s\n", myOrigin.ToString() ); } /* ================ idEntity::MoveJointToJoint HUMANHEAD nla ================ */ void idEntity::MoveJointToJoint( const char *ourBone, idEntity *master, const char *masterBone ) { MoveJointToJointOffset( ourBone, master, masterBone, vec3_origin ); } /* ================ idEntity::MoveJointToJointOffset Offset ourBone location in global space. HUMANHEAD nla ================ */ void idEntity::MoveJointToJointOffset( const char *ourBone, idEntity *master, const char *masterBone, idVec3 &offset ) { jointHandle_t masterJointnum; jointHandle_t ourJointnum; idVec3 masterBoneOrigin; idMat3 masterBoneAxis; idVec3 ourBoneOrigin; idMat3 ourBoneAxis; if ( master == this ) { gameLocal.Error( "Tried to move an object to itself." ); return; } if ( !master->GetAnimator() ) { gameLocal.Error( "Tried to move %s (%s) to a joint on non animated entity %s (%s)\n", name.c_str(), spawnArgs.GetString( "spawnclass" ), master->name.c_str(), master->spawnArgs.GetString( "spawnclass" ) ); } if ( !GetAnimator() ) { gameLocal.Error( "Tried to move via a joint from a non animated entity %s (%s) to\n", name.c_str(), spawnArgs.GetString( "spawnclass" ) ); } masterJointnum = master->GetAnimator()->GetJointHandle( masterBone ); if ( masterJointnum == INVALID_JOINT ) { gameLocal.Error( "Bone '%s' not found.", masterBone ); return; } master->GetAnimator()->GetJointTransform( masterJointnum, gameLocal.time, masterBoneOrigin, masterBoneAxis ); ourJointnum = GetAnimator()->GetJointHandle( ourBone ); if ( ourJointnum == INVALID_JOINT ) { gameLocal.Error( "Bone '%s' not found.", ourBone ); return; } GetAnimator()->GetJointTransform( ourJointnum, gameLocal.time, ourBoneOrigin, ourBoneAxis ); //HUMANHEAD: aob - removed GetPhysics calls SetOrigin( masterBoneOrigin * master->GetAxis() + master->GetOrigin() - ourBoneOrigin * GetAxis() - offset ); //HUMANHEAD END } /* ================ idEntity::AlignToJoint HUMANHEAD nla ================ */ void idEntity::AlignToJoint( idEntity *master, const char *bonename ) { jointHandle_t jointnum; idVec3 boneOrigin; idMat3 boneAxis; if ( master == this ) { gameLocal.Error( "Tried to align an object to itself." ); return; } jointnum = master->GetAnimator()->GetJointHandle( bonename ); if ( jointnum == INVALID_JOINT ) { gameLocal.Error( "Bone '%s' not found.", bonename ); return; } master->GetAnimator()->GetJointTransform( jointnum, gameLocal.time, boneOrigin, boneAxis ); /* gameLocal.Printf( " Before %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", GetPhysics()->GetAxis()[0].x, GetPhysics()->GetAxis()[0].y, GetPhysics()->GetAxis()[0].z, GetPhysics()->GetAxis()[1].x, GetPhysics()->GetAxis()[1].y, GetPhysics()->GetAxis()[1].z, GetPhysics()->GetAxis()[2].x, GetPhysics()->GetAxis()[2].y, GetPhysics()->GetAxis()[2].z ); */ //HUMANHEAD: aob - removed GetPhysics call SetAxis( boneAxis * master->GetAxis() ); //HUMANHEAD END /* gameLocal.Printf( " After %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", GetPhysics()->GetAxis()[0].x, GetPhysics()->GetAxis()[0].y, GetPhysics()->GetAxis()[0].z, GetPhysics()->GetAxis()[1].x, GetPhysics()->GetAxis()[1].y, GetPhysics()->GetAxis()[1].z, GetPhysics()->GetAxis()[2].x, GetPhysics()->GetAxis()[2].y, GetPhysics()->GetAxis()[2].z ); */ } /* ================ idEntity::AlignJointToJoint HUMANHEAD nla ================ */ void idEntity::AlignJointToJoint( const char *ourBone, idEntity *master, const char *masterBone ) { jointHandle_t masterJointnum; jointHandle_t ourJointnum; idVec3 masterBoneOrigin; idMat3 masterBoneAxis; idVec3 ourBoneOrigin; idMat3 ourBoneAxis; if ( master == this ) { gameLocal.Error( "Tried to align an object to itself." ); return; } masterJointnum = master->GetAnimator()->GetJointHandle( masterBone ); if ( masterJointnum == INVALID_JOINT ) { gameLocal.Error( "Bone '%s' not found.", masterBone ); return; } master->GetAnimator()->GetJointTransform( masterJointnum, gameLocal.time, masterBoneOrigin, masterBoneAxis ); ourJointnum = GetAnimator()->GetJointHandle( ourBone ); if ( ourJointnum == INVALID_JOINT ) { gameLocal.Error( "Bone '%s' not found.", ourBone ); return; } GetAnimator()->GetJointTransform( ourJointnum, gameLocal.time, ourBoneOrigin, ourBoneAxis ); /* gameLocal.Printf( " Before B %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", GetPhysics()->GetAxis()[0].x, GetPhysics()->GetAxis()[0].y, GetPhysics()->GetAxis()[0].z, GetPhysics()->GetAxis()[1].x, GetPhysics()->GetAxis()[1].y, GetPhysics()->GetAxis()[1].z, GetPhysics()->GetAxis()[2].x, GetPhysics()->GetAxis()[2].y, GetPhysics()->GetAxis()[2].z ); */ // Bad logic! Fix after fixing the an anim items //HUMANHEAD: aob - removed GetPhysics calls SetAxis( ( ( ( masterBoneAxis * master->GetAxis() ).ToAngles() - ( ourBoneAxis * GetAxis() ).ToAngles() ) + GetAxis().ToAngles() ).ToMat3() ); //HUMANHEAD END /* gameLocal.Printf( " After B %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", GetPhysics()->GetAxis()[0].x, GetPhysics()->GetAxis()[0].y, GetPhysics()->GetAxis()[0].z, GetPhysics()->GetAxis()[1].x, GetPhysics()->GetAxis()[1].y, GetPhysics()->GetAxis()[1].z, GetPhysics()->GetAxis()[2].x, GetPhysics()->GetAxis()[2].y, GetPhysics()->GetAxis()[2].z ); */ // SetAxis( ( ( ( ourBoneAxis * GetPhysics()->GetAxis() ).ToAngles() - ( masterBoneAxis * master->GetPhysics()->GetAxis() ).ToAngles() ) + GetPhysics()->GetAxis().ToAngles() ).ToMat3() ); } /* ================== idEntity::SpawnFXLocal ================== */ //HUMANHEAD rww - added forceClient hhEntityFx* idEntity::SpawnFxLocal( const char *fxName, const idVec3 &origin, const idMat3& axis, const hhFxInfo* const fxInfo, bool forceClient ) { idDict fxArgs; hhEntityFx * fx = NULL; if ( g_skipFX.GetBool() ) { return NULL; } if( !fxName || !fxName[0] ) { return NULL; } // Spawn an fx fxArgs.Set( "fx", fxName ); fxArgs.SetBool( "start", fxInfo ? fxInfo->StartIsSet() : true ); fxArgs.SetVector( "origin", origin ); fxArgs.SetMatrix( "rotation", axis ); //HUMANHEAD: aob if( fxInfo ) { fxArgs.SetBool( "removeWhenDone", fxInfo->RemoveWhenDone() ); fxArgs.SetBool( "onlyVisibleInSpirit", fxInfo->OnlyVisibleInSpirit() ); // CJR fxArgs.SetBool( "onlyInvisibleInSpirit", fxInfo->OnlyInvisibleInSpirit() ); // tmj fxArgs.SetBool( "toggle", fxInfo->Toggle() ); fxArgs.SetBool( "triggered", fxInfo->Triggered() ); // mdl } //HUMANHEAD END //HUMANHEAD rww - use forceClient if (forceClient) { //this can happen on the "server" in the case of listen servers as well fx = (hhEntityFx *)gameLocal.SpawnClientObject( "func_fx", &fxArgs ); } else { assert(!gameLocal.isClient); fx = (hhEntityFx *)gameLocal.SpawnObject( "func_fx", &fxArgs ); } if( fxInfo ) { fx->SetFxInfo( *fxInfo ); } if( fxInfo && fxInfo->EntityIsSet() ) { fx->fl.noRemoveWhenUnbound = fxInfo->NoRemoveWhenUnbound(); if( fxInfo->BindBoneIsSet() ) { fx->MoveToJoint( fxInfo->GetEntity(), fxInfo->GetBindBone() ); fx->BindToJoint( fxInfo->GetEntity(), fxInfo->GetBindBone(), true ); } else if( fx && fx->Joint() && *fx->Joint() ) { fx->MoveToJoint( fxInfo->GetEntity(), fx->Joint() ); fx->BindToJoint( fxInfo->GetEntity(), fx->Joint(), true ); } else { fx->Bind( fxInfo->GetEntity(), true ); } } fx->Show(); return fx; } /* ================== idEntity::SpawnFXPrefixLocal ================== */ void idEntity::SpawnFXPrefixLocal( const idDict* dict, const char* fxKeyPrefix, const idVec3& origin, const idMat3& axis, const hhFxInfo* const fxInfo, const idEventDef* eventDef ) { hhEntityFx* fx = NULL; for( const idKeyValue* kv = dict->MatchPrefix(fxKeyPrefix); kv; kv = dict->MatchPrefix(fxKeyPrefix, kv) ) { if( !kv->GetValue().Length() ) { continue; } fx = SpawnFxLocal( kv->GetValue().c_str(), origin, axis, fxInfo, true ); if( eventDef ) { ProcessEvent( eventDef, fx ); } } } /* ================ idEntity::GetMasterDefaultPosition HUMANHEAD: aob - helper function to be overridden ================ */ void idEntity::GetMasterDefaultPosition( idVec3 &masterOrigin, idMat3 &masterAxis ) const { //HUMANHEAD: aob - if modelDefHandle is valid then we know that renderEntity values are valid masterOrigin = (bindMaster->modelDefHandle == -1) ? bindMaster->GetOrigin() : bindMaster->GetRenderEntity()->origin; masterAxis = (bindMaster->modelDefHandle == -1) ? bindMaster->GetAxis() : bindMaster->GetRenderEntity()->axis; //HUMANHEAD END } /* ================ idEntity::Event_SpawnDebris //HUMANHEAD: jrm ================ */ void idEntity::Event_SpawnDebris(const char *debrisKey) { if (GetPhysics()) { idMat3 rot = GetPhysics()->GetAxis(); idVec3 fw = rot[0]; idVec3 orig = GetPhysics()->GetOrigin(); idVec3 vel = rot[2]; idActor *act = NULL; if(IsType(idActor::Type)) { act = (idActor*)this; } if(act) { orig = act->GetEyePosition(); if (GetPhysics()->IsType(idPhysics_Monster::Type)) { idPhysics_Monster *mp = (idPhysics_Monster*)GetPhysics(); idVec3 delta = mp->GetDelta(); vel = mp->GetDelta() * USERCMD_HZ; } } if (debrisKey) { const char *debrisName = spawnArgs.GetString(debrisKey, NULL); hhUtils::SpawnDebrisMass(debrisName, orig, &fw, &vel); } } } /* ================ idEntity::DrawDebug HUMANHEAD pdm ================ */ void idEntity::DrawDebug(int page) { idStr text; idPhysics *phys = GetPhysics(); if (phys) { hhUtils::DebugAxis(phys->GetOrigin(), phys->GetAxis(), 30, 0); idVec3 vel = phys->GetLinearVelocity(); gameRenderWorld->DebugArrow(colorGreen, phys->GetOrigin(), phys->GetOrigin() + vel, 10); sprintf(text, "Mass=%.2f", phys->GetMass()); idMat3 axis = gameLocal.GetLocalPlayer()->viewAngles.ToMat3(); gameRenderWorld->DrawText(text, GetOrigin(), 0.4f, colorRed, axis); } } /* ================ idEntity::FillDebugVars HUMANHEAD pdm ================ */ void idEntity::FillDebugVars(idDict *args, int page) { idStr text; switch(page) { case 1: args->Set("class", GetClassname()); args->Set("name", name.c_str()); args->SetInt("modelHandle", modelDefHandle); args->Set("bindMaster", bindMaster ? bindMaster->name.c_str() : "none"); // args->Set("skin", renderEntity.customSkin ? renderEntity.customSkin->name : "none"); args->SetInt("health", health); if (GetPhysics()) { args->Set("physics", GetPhysics()->GetType()->classname); if (GetPhysics()->GetNumClipModels() > 1) { args->SetInt("Bodies", GetPhysics()->GetNumClipModels()); for (int ix=0; ixGetNumClipModels(); ix++) { text = collisionModelManager->ContentsName(GetPhysics()->GetContents(ix)); args->Set(va("Body %d contents", ix), text); text = collisionModelManager->ContentsName(GetPhysics()->GetClipMask(ix)); args->Set(va("Body %d clipmask", ix), text); } } else { text = collisionModelManager->ContentsName(GetPhysics()->GetContents()); args->Set("contents", text); text = collisionModelManager->ContentsName(GetPhysics()->GetClipMask()); args->Set("clipmask", text); } } else { args->Set("physics", "none"); } args->SetBool("dormant", fl.isDormant); text.Empty(); if (fl.noRemoveWhenUnbound) text += "noRemoveWhenUnbound "; if (fl.refreshReactions) text += "refreshReactions "; if (fl.touchTriggers) text += "touchTriggers "; if (fl.notarget) text += "notarget "; if (fl.noknockback) text += "noknockback "; if (fl.takedamage) text += "takedamage "; if (fl.hidden) text += "hidden "; if (fl.bindOrientated) text += "bindOriented "; if (fl.solidForTeam) text += "solidForTeam "; if (fl.forcePhysicsUpdate) text += "forcePhysicsUpdate "; if (fl.selected) text += "selected "; if (fl.neverDormant) text += "neverDormant "; if (fl.isDormant) text += "isDormant "; if (fl.hasAwakened) text += "hasAwakened "; args->Set("flags", text.c_str()); break; case 2: // Physics page if (GetPhysics()) { args->Set("physics", GetPhysics()->GetType()->classname); text = collisionModelManager->ContentsName(GetPhysics()->GetContents()); args->Set("contents", text); text = collisionModelManager->ContentsName(GetPhysics()->GetClipMask()); args->Set("clipmask", text); text = GetPhysics()->GetGravity().ToString(2); args->Set("gravity", text); text = GetPhysics()->GetOrigin().ToString(2); args->Set("origin", text); text = GetPhysics()->GetAxis().ToString(2); args->Set("axis", text); args->SetFloat("mass", GetPhysics()->GetMass()); args->SetFloat("speed", GetPhysics()->GetLinearVelocity().Length() ); } else { args->Set("physics", "none"); } case 3: break; } } /* ===================== idEntity::SetHealth //HUMANHEAD: aob ===================== */ void idEntity::SetHealth( const int newHealth ) { // JRM if(newHealth > health) lastHealTime = gameLocal.GetTime(); health = (newHealth < GetMaxHealth()) ? newHealth : GetMaxHealth(); } /* ===================== idEntity::GetHealthLevel //HUMANHEAD: aob ===================== */ float idEntity::GetHealthLevel() { return ( (float)GetHealth() / (float)GetMaxHealth() ); } /* ===================== idEntity::GetWoundLevel //HUMANHEAD: aob ===================== */ float idEntity::GetWoundLevel() { return 1.0f - GetHealthLevel(); } /* ===================== idEntity::SwapBindInfo HUMANHEAD pdm: Swaps the bindings of two entities, used for spiritwalking while bound ===================== */ bool idEntity::SwapBindInfo(idEntity *ent2) { idEntity *ent1 = this; if (!ent1->IsBound() && !ent2->IsBound()) { return false; } idEntity *master1 = ent1->bindMaster; idEntity *master2 = ent2->bindMaster; jointHandle_t joint1 = ent1->bindJoint; jointHandle_t joint2 = ent2->bindJoint; int body1 = ent1->bindBody; int body2 = ent2->bindBody; bool oriented1 = ent1->fl.bindOrientated; bool oriented2 = ent2->fl.bindOrientated; const char *bone1; const char *bone2; ent1->Unbind(); ent2->Unbind(); // Bind ent2 to what ent1 was bound to if (master1 != NULL) { if (joint1 != INVALID_JOINT) { bone1 = master1->GetAnimator()->GetJointName(joint1); ent2->BindToJoint(master1, bone1, oriented1); } else if (body1 >= 0) { ent2->BindToBody(master1, body1, oriented1); } else { ent2->Bind(master1, oriented1); } } // Bind ent1 to what ent2 was bound to if (master2 != NULL) { if (joint2 != INVALID_JOINT) { bone2 = master2->GetAnimator()->GetJointName(joint2); ent1->BindToJoint(master2, bone2, oriented2); } else if (body2 >= 0) { ent1->BindToBody(master2, body2, oriented2); } else { ent1->Bind(master2, oriented2); } } return true; } /* ===================== idEntity::AllowCollision HUMANHEAD: pdm/aob ===================== */ bool idEntity::AllowCollision( const trace_t &collision ) { return true; } /* ===================== idEntity::GetAimPosition HUMANHEAD: pdm ===================== */ idVec3 idEntity::GetAimPosition() const { idVec3 offset = spawnArgs.GetVector( "offset_aim" ); return GetOrigin() + offset * GetAxis(); } /* ===================== idEntity::PlayImpactSound Colliding objects should call their own versions of this( aka movables and projectiles ) ===================== */ int idEntity::PlayImpactSound( const idDict* dict, const idVec3 &origin, surfTypes_t type ) { const char *snd = gameLocal.MatterTypeToMatterKey( "snd_impact", type ); if( !snd || !snd[0] || !dict ) { return -1; } int length = 0; StartSoundShader( declManager->FindSound(dict->GetString(snd), false), SND_CHANNEL_BODY, 0, false, &length ); return length; } /* ============== idEntity::AddLocalMatterWound HUMANHEAD: aob ============== */ void idEntity::AddLocalMatterWound( jointHandle_t jointNum, const idVec3 &localOrigin, const idVec3 &localNormal, const idVec3 &localDir, int damageDefIndex, const idMaterial *collisionMaterial ) { PROFILE_SCOPE("AddLocalMatterWound", PROFMASK_COMBAT); const idDeclEntityDef *def = static_cast( declManager->DeclByIndex( DECL_ENTITYDEF, damageDefIndex ) ); if ( def == NULL ) { return; } surfTypes_t matterType = gameLocal.GetMatterType( this, collisionMaterial, "idEntity::AddLocalMatterWound" ); GetWoundManager()->AddWounds( def, matterType, jointNum, localOrigin, localNormal, localDir ); //Not sure we need to do anything special with the head. It should have its own collision //TODO: Grab head projection code from below and put into ApplyImpactMark() } /* =============== idEntity::Event_DamageEntity HUMANHEAD: nla =============== */ void idEntity::Event_DamageEntity( idEntity *target, const char *damageDefName ) { assert( target ); assert( damageDefName ); target->Damage( this, this, idVec3( 0, 0, 0 ), damageDefName, 1.0f, INVALID_JOINT ); } /* =============== idEntity::Event_DelayDamageEntity HUMANHEAD: jrm: for scripts to call =============== */ void idEntity::Event_DelayDamageEntity( idEntity *target, const char *damageDefName, float secs ) { const idDeclEntityDef *damageDecl = gameLocal.FindEntityDef(damageDefName, false); if (damageDecl == NULL) { gameLocal.Warning("delayDamageEntity: invalid damage type: %s\n", damageDefName); return; } PostEventSec(&EV_DamageEntity, secs, target, damageDefName); } //TODO: Move this dispose logic to idActor? (monsters and player) /* ============== idEntity::Event_Dispose HUMANHEAD nla ============== */ void idEntity::Event_Dispose() { if( fl.disposed ) { return; } fl.disposed = true; fl.takedamage = false; GetPhysics()->SetContents( 0 ); GetPhysics()->SetClipMask( 0 ); GetPhysics()->UnlinkClip(); //GetPhysics()->PutToRest(); RemoveBinds(); idVec3 origin = GetOrigin(); // This might be slightly up in the air because it's the origin of the ragdoll trace_t trace; memset(&trace, 0, sizeof(trace_t)); if (gameLocal.clip.TracePoint( trace, origin, origin+gameLocal.GetGravityNormal()*50, CONTENTS_SOLID, NULL )) { origin = trace.endpos - gameLocal.GetGravityNormal() * 5; // 5 units up from ground } hhFxInfo fxInfo; fxInfo.RemoveWhenDone( true ); BroadcastFxInfoPrefixed( "fx_deatheffect", origin, GetAxis(), &fxInfo ); // Start the transition out , remove when transition is done. renderEntity.noShadow = true; if( modelDefHandle > 0 && !spawnArgs.GetBool("keepDecals") ) { gameRenderWorld->RemoveDecals( modelDefHandle ); } SetShaderParm(SHADERPARM_TIME_OF_DEATH, MS2SEC(gameLocal.time)); // SetDeformation(DEFORMTYPE_DEATHEFFECT, gameLocal.time, 5000); // starttime, duration PostEventMS( &EV_Remove, 5000 ); } /* ============== idEntity::StartDisposeCountdown HUMANHEAD nla ============== */ void idEntity::StartDisposeCountdown() { float delay = spawnArgs.GetFloat( "dispose_delay", "2" ); CancelEvents( &EV_Dispose ); PostEventSec( &EV_Dispose, delay ); } /* ============================== idEntity::GetChannelForAnim Given a group name, return the corresponding channel If no group matches, channel 0 is returned HUMANHEAD pdm: exposed this channel utility function for all entities ============================== */ int idEntity::GetChannelForAnim( const char *anim ) const { const char *channelName; int channel; channelName = GetChannelNameForAnim( anim ); if ( !channelName || !channelName[0] ) { return( 0 ); } channel = ChannelName2Num( channelName ); if ( channel < 0 ) { return( 0 ); } return( channel ); } /* =========================== idEntity::ChannelName2Num Given a channel name, return the channel to play on Returns -1 if none found, else the proper channel num HUMANHEAD nla =========================== */ int idEntity::ChannelName2Num( const char *channelName ) const { if ( GetAnimator() && GetAnimator()->ModelDef() ) { return( GetAnimator()->ModelDef()->channelDict.GetInt( channelName, "-1" ) ); } return( -1 ); } /* =========================== idEntity::GetChannelNameForAnim Given a channel name, return the channel to play on Returns NULL if none found, else the proper channel num HUMANHEAD nla =========================== */ const char * idEntity::GetChannelNameForAnim( const char *animName ) const { if ( GetAnimator() && GetAnimator()->ModelDef() ) { return( GetAnimator()->ModelDef()->channelDict.GetString( va( "channel4anim_%s", animName ), NULL ) ); } return( NULL ); } /* =============== idEntity::SetSoundMinDistance HUMANHEAD: aob =============== */ void idEntity::SetSoundMinDistance( float minDistance, const s_channelType channel ) { if( !refSound.referenceSound ) { return; } #ifdef ID_ALLOW_SOUND_MODIFY hhSoundShaderParmsModifier modifierParms; modifierParms.SetMinDistance( minDistance ); refSound.referenceSound->ModifySound( NULL, channel, modifierParms ); #endif } /* =============== idEntity::SetSoundMaxDistance HUMANHEAD: aob =============== */ void idEntity::SetSoundMaxDistance( float maxDistance, const s_channelType channel ) { if( !refSound.referenceSound ) { return; } #ifdef ID_ALLOW_SOUND_MODIFY hhSoundShaderParmsModifier modifierParms; modifierParms.SetMaxDistance( maxDistance ); refSound.referenceSound->ModifySound( NULL, channel, modifierParms ); #endif } /* =============== idEntity::HH_SetSoundVolume HUMANHEAD: aob: takes a linear [0..1] volume =============== */ void idEntity::HH_SetSoundVolume( float volume, const s_channelType channel ) { if( !refSound.referenceSound ) { return; } // Convert from linear volume to dB float dB = hhMath::Scale2dB(volume); #ifdef ID_ALLOW_SOUND_MODIFY hhSoundShaderParmsModifier modifierParms; modifierParms.SetVolume( dB ); refSound.referenceSound->ModifySound( NULL, channel, modifierParms ); #endif } float idEntity::GetVolume( const s_channelType channel ) { if( !refSound.referenceSound ) { return 0.0f; } #ifdef ID_ALLOW_SOUND_MODIFY soundShaderParms_t *ssp = refSound.referenceSound->GetSoundParms(NULL, channel); return hhMath::dB2Scale(ssp->volume); #else return 1.0f; #endif } /* =============== idEntity::SetSoundShakes HUMANHEAD: aob =============== */ void idEntity::SetSoundShakes( float shakes, const s_channelType channel ) { if( !refSound.referenceSound ) { return; } #ifdef ID_ALLOW_SOUND_MODIFY hhSoundShaderParmsModifier modifierParms; modifierParms.SetShakes( shakes ); refSound.referenceSound->ModifySound( NULL, channel, modifierParms ); #endif } /* =============== idEntity::SetSoundShaderFlags HUMANHEAD: aob =============== */ void idEntity::SetSoundShaderFlags( int flags, const s_channelType channel ) { if( !refSound.referenceSound ) { return; } #ifdef ID_ALLOW_SOUND_MODIFY hhSoundShaderParmsModifier modifierParms; modifierParms.SetSoundShaderFlags( flags ); refSound.referenceSound->ModifySound( NULL, channel, modifierParms ); #endif } /* =============== idEntity::FadeSoundShader HUMANHEAD: aob =============== */ void idEntity::FadeSoundShader( int to, int over, const s_channelType channel ) { if( !refSound.referenceSound ) { return; } refSound.referenceSound->FadeSound( channel, to, over ); } /* =============== idEntity::Event_ResetGravity HUMANHEAD: pdm: Posted when entity is leaving a gravity zone =============== */ void idEntity::Event_ResetGravity() { idVec3 localGravityDir = hhUtils::GetLocalGravity( GetOrigin(), GetPhysics()->GetBounds(), gameLocal.GetGravity() ); float gravityMagnitude = spawnArgs.GetFloat( "gravity", va("%.2f", localGravityDir.Normalize()) ); GetPhysics()->SetGravity( gravityMagnitude * localGravityDir ); GetPhysics()->Activate(); } // // Event_LoadReactions() // HUMANHEAD JRM void idEntity::Event_LoadReactions() { LoadReactions(); } // // LoadReactions() // // HUMANHEAD JRM // #define MaxNumReactions 16 void idEntity::LoadReactions() { assert(reactions.Num() <= 0); // Can't have any loaded still! // Loop through each one in ORDER so the array list is ordered properly (so we can reference later by index if we want) idStr keyName; idStr reactPrefix; for(int i=0;i 0) { keyName = idStr("def_reaction") + idStr(i); reactPrefix = idStr("reaction") + idStr(i) + idStr("_"); } else { keyName = idStr("def_reaction"); reactPrefix = idStr("reaction_"); } // Hit the end of our list const idKeyValue *kv = spawnArgs.FindKey((const char*)keyName); if(!kv) break; // Store unique keys if the user specified them specifically // ie. "reaction1_cause" to override from the default idDict uniqueKeys; uniqueKeys.Clear(); const idKeyValue *reactKeyVal = spawnArgs.MatchPrefix(reactPrefix.c_str(), NULL); while(reactKeyVal) { uniqueKeys.Set(reactKeyVal->GetKey().c_str(), reactKeyVal->GetValue().c_str()); reactKeyVal = spawnArgs.MatchPrefix(reactPrefix.c_str(), reactKeyVal); } const char *name = (const char*)kv->GetValue(); if (name && name[0]) { const hhReactionDesc *rd = gameLocal.GetReactionHandler()->LoadReactionDesc(name, uniqueKeys); assert(rd != NULL); hhReaction *newReaction = new hhReaction(); newReaction->desc = rd; newReaction->causeEntity = this; // By default, all messages sent by us mean that the cause is US newReaction->effectEntity.Resize(8, 8); // Try to avoid lots of mem allocations reactions.Append(newReaction); } } fl.refreshReactions = FALSE; if(reactions.Num() > 0) { fl.refreshReactions = spawnArgs.GetBool("reaction_enabled", "1"); } } /* ============================== idEntity::PickRandomTarget HUMANHEAD: aob ============================== */ idEntity* idEntity::PickRandomTarget() { RemoveNullTargets(); if( !targets.Num() ) { return NULL; } return targets[ gameLocal.random.RandomInt(targets.Num()) ].GetEntity(); } //---------------------------------------------- // // MSCallback // //---------------------------------------------- bool idEntity::MSCallback( renderEntity_s *renderEntity, const renderView_t *renderView, int ms) { const idEntity *ent = gameLocal.entities[ renderEntity->entityNum ]; if ( !ent ) { gameLocal.Error( "idEntity::MSCallback: callback with NULL game entity" ); } bool animChanged = false; bool deformChanged = false; // If this entity is animated, issue that callback if (ent->animCallback) { animChanged = ent->animCallback(renderEntity, renderView); } if ( renderView && renderView->time >= ent->nextCallbackTime ) { ent->nextCallbackTime = renderView->time + ms; deformChanged = true; } return (animChanged || deformChanged); } bool idEntity::TenHertzCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) { return idEntity::MSCallback(renderEntity, renderView, 100); } bool idEntity::TwentyHertzCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) { return idEntity::MSCallback(renderEntity, renderView, 50); } bool idEntity::ThirtyHertzCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) { return idEntity::MSCallback(renderEntity, renderView, 33); } bool idEntity::SixtyHertzCallback( renderEntity_s *renderEntity, const renderView_t *renderView ) { return idEntity::MSCallback(renderEntity, renderView, 16); } /* ============================== idEntity::SetDeformCallback HUMANHEAD: pdm: set appropriate callback for the current deform. ============================== */ void idEntity::SetDeformCallback() { int deformType = renderEntity.shaderParms[SHADERPARM_ANY_DEFORM]; if (deformType == DEFORMTYPE_NONE) { return; } // Store animation callback if it exists, so we can piggy back it onto ours if (renderEntity.callback == idEntity::ModelCallback) { animCallback = renderEntity.callback; } else { animCallback = NULL; } // All deform types that run on their own timer need a callback entry in here switch(deformType) { case DEFORMTYPE_PLANTSWAYX: case DEFORMTYPE_PLANTSWAYY: case DEFORMTYPE_RIPPLE: case DEFORMTYPE_RIPPLECENTER: case DEFORMTYPE_TURBULENT: case DEFORMTYPE_RAYS: case DEFORMTYPE_ALPHAGLOW: renderEntity.callback = idEntity::TwentyHertzCallback; nextCallbackTime = gameLocal.time; break; case DEFORMTYPE_VIBRATE: renderEntity.callback = idEntity::ThirtyHertzCallback; nextCallbackTime = gameLocal.time; break; case DEFORMTYPE_PORTAL: case DEFORMTYPE_DEATHEFFECT: // Callback for these already used for animation case DEFORMTYPE_POD: case DEFORMTYPE_WINDBLAST: renderEntity.callback = idEntity::SixtyHertzCallback; nextCallbackTime = gameLocal.time; break; default: break; } } /* ============================== idEntity::SetDeformationOnRenderEntity HUMANHEAD pdm Translates game deformations into the proper format for the renderer. This is done because the shaderparms all default to zero, and sometimes we want to be able to specify our parms in the range of [0..1] for example, therefore we translate the parms into a different range. This renderentity only version is so the spawnargs can be parsed and passed to it. ============================== */ void SetDeformationOnRenderEntity(renderEntity_t *renderEntity, int deformType, float parm1, float parm2) { float value1 = parm1; float value2 = parm2; // Do any shaderparm storage translation here. We like to expose user friendly ranges to the users, // but internally we sometimes store the values differently. switch(deformType) { case DEFORMTYPE_SCALE: value1 = hhMath::hhMax( 0.0f, parm1 );//aob - make sure we don't go below 0.0 break; case DEFORMTYPE_POD: value2 = hhMath::hhMax( 0.0f, parm2 );//aob - make sure we don't go below 0.0 break; case DEFORMTYPE_VERTEXCOLOR: value1 = parm1 + 1.0f; // Game code passes in [0..1], we store as [1..2], pass in -1 to stop using break; default: break; } renderEntity->shaderParms[ SHADERPARM_ANY_DEFORM ] = (float)deformType; renderEntity->shaderParms[ SHADERPARM_ANY_DEFORM_PARM1 ] = value1; renderEntity->shaderParms[ SHADERPARM_ANY_DEFORM_PARM2 ] = value2; } void idEntity::SetDeformation(int deformType, float parm1, float parm2) { SetDeformationOnRenderEntity(&renderEntity, deformType, parm1, parm2); UpdateVisuals(); } void idEntity::Event_SetDeformation(int deformType, float parm1, float parm2) { SetDeformation(deformType, parm1, parm2); } void idEntity::Event_SetPortalCollision( int collide ) { // CJR this->fl.noPortal = collide ? true: false; // damn compiler warning } bool idEntity::IsScaled() { int deformType = (int)renderEntity.shaderParms[ SHADERPARM_ANY_DEFORM ]; float scale; switch(deformType) { case DEFORMTYPE_SCALE: scale = renderEntity.shaderParms[ SHADERPARM_ANY_DEFORM_PARM1 ]; return (scale != 0.0f && scale != 1.0f); break; } return false; } float idEntity::GetScale() { int deformType = (int)renderEntity.shaderParms[ SHADERPARM_ANY_DEFORM ]; switch(deformType) { case DEFORMTYPE_SCALE: return renderEntity.shaderParms[ SHADERPARM_ANY_DEFORM_PARM1 ]; break; } return 1.0f; } // Method to handle named event on all of an entity's guis, and handle any resulting commands // If your cmds are getting ignored when set in a namedEvent, you aren't call this to issue it void idEntity::CallNamedEvent(const char *eventName) { const char *command = NULL; sysEvent_t ev; memset( &ev, 0, sizeof( ev ) ); ev.evType = SE_NONE; for (int ix=0; ixHandleNamedEvent(eventName); // Now, make sure the pending command gets processed by forcing a HandleEvent call command = renderEntity.gui[ix]->HandleEvent( &ev, gameLocal.time ); HandleGuiCommands( this, command ); } } } /* ================ idEntity::BroadcastEventReroute HUMANHEAD: aob ================ */ void idEntity::BroadcastEventReroute( int eventId, const idBitMsg *msg, bool saveEvent, int excludeClient ) { //If in single player, send event back to entity if( !gameLocal.isMultiplayer && !gameLocal.isClient ) { ClientReceiveEvent( eventId, gameLocal.GetTime(), *msg ); } else { assert(!gameLocal.isClient); ServerSendEvent(eventId, msg, saveEvent, excludeClient); //rww - if this is a listen server we want to both broadcast and receieve locally if (gameLocal.GetLocalPlayer()) { ClientReceiveEvent( eventId, gameLocal.GetTime(), *msg ); } } } /* ================ idEntity::BroadcastSpawn HUMANHEAD: aob ================ */ void idEntity::BroadcastEventDef( const idEventDef& eventDef ) { idBitMsg msg; byte msgBuf[MAX_EVENT_PARAM_SIZE]; msg.Init( msgBuf, sizeof( msgBuf ) ); msg.BeginWriting(); msg.WriteShort( eventDef.GetEventNum() ); BroadcastEventReroute( EVENT_EVENTDEF, &msg ); } /* ================ idEntity::BroadcastSpawnDecl HUMANHEAD: aob ================ */ void idEntity::BroadcastDecl( declType_t type, const char* defName, const idEventDef& eventDef ) { idBitMsg msg; byte msgBuf[MAX_EVENT_PARAM_SIZE]; const idDecl* decl = NULL; if( !defName || !defName[0] ) { return; } decl = declManager->FindType( type, defName, false ); if( !decl ) { return; } msg.Init( msgBuf, sizeof( msgBuf ) ); msg.BeginWriting(); msg.WriteBits( (int)type, DECL_MAX_TYPES_NUM_BITS ); msg.WriteShort( decl->Index() ); msg.WriteBits( eventDef.GetEventNum(), MAX_EVENTS_NUM_BITS ); BroadcastEventReroute( EVENT_DECL, &msg ); } /* ================ idEntity::BroadcastSpawnFx HUMANHEAD: aob ================ */ void idEntity::BroadcastFx( const char* defName, const idEventDef& eventDef ) { const idDecl* decl = declManager->FindType( DECL_FX, defName, false ); if( decl ) { ProcessEvent( &eventDef, decl->GetName() ); } } /* ================ idEntity::BroadcastSpawnEntityDef HUMANHEAD: aob ================ */ void idEntity::BroadcastEntityDef( const char* defName, const idEventDef& eventDef ) { BroadcastDecl( DECL_ENTITYDEF, defName, eventDef ); } /* ================ idEntity::BroadcastBeam HUMANHEAD: aob ================ */ void idEntity::BroadcastBeam( const char* defName, const idEventDef& eventDef ) { BroadcastDecl( DECL_BEAM, defName, eventDef ); } /* ================== idEntity::BroadcastFxInfo HUMANHEAD: aob ================== */ void idEntity::BroadcastFxInfo( const char* fx, const idVec3& origin, const idMat3& axis, const hhFxInfo* const fxInfo, const idEventDef* eventDef, bool broadcast ) { /* idBitMsg msg; byte msgBuf[MAX_EVENT_PARAM_SIZE]; hhFxInfo localDummyFxInfo; const hhFxInfo* localFxInfo = (fxInfo) ? fxInfo : &localDummyFxInfo; msg.Init( msgBuf, sizeof( msgBuf ) ); msg.BeginWriting(); //FIXME: try and find a way to pass the decl index instead of a string msg.WriteString( fx ); msg.WriteVec3( origin ); msg.WriteMat3( axis ); localFxInfo->WriteToBitMsg( &msg ); msg.WriteBits( (eventDef) ? eventDef->GetEventNum() : -1, MAX_EVENTS_NUM_BITS ); BroadcastEventReroute( EVENT_FX_INFO, &msg ); */ //rww - call to SpawnFxLocal and it will take care of client-server stuff based on where we are calling from. if (gameLocal.isClient && broadcast) { //don't spawn broadcast fx on the client. return; } hhEntityFx* efx = SpawnFxLocal( fx, origin, axis, fxInfo, gameLocal.isClient ); if (efx) { efx->fl.networkSync = broadcast; if( eventDef ) { ProcessEvent( eventDef, efx ); } } } /* ================== idEntity::BroadcastFxInfoPrefixed HUMANHEAD aob ================== */ //FIXME: this could be done in a local event and be much cheaper void idEntity::BroadcastFxInfoPrefixed( const char *fxPrefix, const idVec3 &origin, const idMat3& axis, const hhFxInfo* const fxInfo, const idEventDef* eventDef, bool broadcast ) { if ( g_skipFX.GetBool() ) { return; } const idKeyValue* kv = spawnArgs.MatchPrefix( fxPrefix ); while( kv ) { if( kv->GetValue().Length() ) { BroadcastFxInfo( kv->GetValue().c_str(), origin, axis, fxInfo, eventDef, broadcast ); } kv = spawnArgs.MatchPrefix( fxPrefix, kv ); } } /* ================== idEntity::BroadcastFxInfoPrefixedRandom HUMANHEAD aob ================== */ //FIXME: this could be done in a local event and be much cheaper void idEntity::BroadcastFxInfoPrefixedRandom( const char *fxPrefix, const idVec3 &origin, const idMat3& axis, const hhFxInfo* const fxInfo, const idEventDef* eventDef ) { if ( g_skipFX.GetBool() ) { return; } const char* fxName = spawnArgs.RandomPrefix( fxPrefix, gameLocal.random ); if( !fxName || !fxName[0] ) { return; } BroadcastFxInfo( fxName, origin, axis, fxInfo, eventDef ); } /* ================== idEntity::BroadcastFxPrefixedRandom HUMANHEAD ckr ================== */ void idEntity::BroadcastFxPrefixedRandom( const char *fxPrefix, const idEventDef &eventDef ) { if ( g_skipFX.GetBool() ) { return; } const char* fxName = spawnArgs.RandomPrefix( fxPrefix, gameLocal.random ); if( !fxName || !fxName[0] ) { return; } BroadcastFx( fxName, eventDef ); } /* ================ idEntity::Event_SetFloatKey ================ */ void idEntity::Event_SetFloatKey( const char *key, float value ) { spawnArgs.SetFloat( key, value ); } /* ================ idEntity::Event_SetVectorKey ================ */ void idEntity::Event_SetVectorKey( const char *key, const idVec3& value ) { spawnArgs.SetVector( key, value ); } /* ================ idEntity::Event_SetEntityKey ================ */ void idEntity::Event_SetEntityKey( const char *key, const idEntity* value ) { HH_ASSERT( value ); spawnArgs.Set( key, value->GetName() ); } //============================================================================= // // idEntity::Event_PlayerCanSee // // // HUMANHEAD CJR //============================================================================= void idEntity::Event_PlayerCanSee() { int i; idEntity *ent; hhPlayer *player; trace_t traceInfo; idEntity *selfCheck; // Is either the entity or the master // Check if this entity is in the player's PVS if ( gameLocal.InPlayerPVS( this ) ) { for ( i = 0; i < gameLocal.numClients ; i++ ) { ent = gameLocal.entities[ i ]; if ( !ent || !ent->IsType( hhPlayer::Type ) ) { continue; } // Get the player player = static_cast( ent ); // Check if the entity is in the player's FOV, based upon the "fov" key/value if ( !player->CheckFOV( this->GetOrigin() ) ) { continue; } if ( this->GetBindMaster() ) { selfCheck = this->GetBindMaster(); } else { selfCheck = this; } // Check if a trace succeeds from the player to the entity gameLocal.clip.TracePoint( traceInfo, player->GetEyePosition(), this->GetOrigin(), MASK_SHOT_RENDERMODEL, player ); if ( traceInfo.fraction >= 1.0f || ( gameLocal.GetTraceEntity( traceInfo ) == selfCheck ) ) { idThread::ReturnInt( true ); return; } } } idThread::ReturnInt( false ); } void idEntity::ActivatePrefixed(const char *prefix, idEntity *activator) { const idKeyValue *kv = spawnArgs.MatchPrefix( prefix ); while( kv ) { idEntity *ent = gameLocal.FindEntity( kv->GetValue() ); if ( ent ) { if ( ent && ent->RespondsTo( EV_Activate ) || ent->HasSignal( SIG_TRIGGER ) ) { ent->Signal( SIG_TRIGGER ); ent->ProcessEvent( &EV_Activate, activator ); } for ( int j = 0; j < MAX_RENDERENTITY_GUI; j++ ) { if ( ent->renderEntity.gui[ j ] ) { ent->renderEntity.gui[ j ]->Trigger( gameLocal.time ); } } } kv = spawnArgs.MatchPrefix( prefix, kv ); } } void idEntity::SquishedByDoor(idEntity *door) { } // All the different types of doors do this for theirselves, teammates, and buddies float idEntity::GetDoorShaderParm(bool locked, bool startup) { float parmValue; // At startup: // shaderparm7: 3=alwayslocked, 2=locked, 1=unlocked, 0=never locked // When locking/unlocking: // shaderparm7: 3=alwayslocked, 2=locked, 1=unlocked, 0=never locked // alwaysLocked overrides all as they want to adjust colors manually bool alwaysLocked = spawnArgs.GetBool("alwaysLocked"); // parmValue = alwaysLocked ? 0.0f : locked ? 2.0f : startup ? 0.0f : 1.0f; parmValue = alwaysLocked ? 3.0f : locked ? 2.0f : startup ? 0.0f : 1.0f; return parmValue; } void idEntity::Event_KillBox( void ) { gameLocal.KillBox(this, false); } //HUMANHEAD rww void idEntity::Event_Remove( void ) { if (gameLocal.isClient && !fl.clientEntity) { //do not ever event-remove ents which could be in the snapshot on the client. Hide(); return; } delete this; } //HUMANHEAD END