/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ #include "EntitiesMP/StdH/StdH.h" #include "EntitiesMP/Reminder.h" #include "EntitiesMP/Flame.h" #include "EntitiesMP/Debris.h" #include "EntitiesMP/Player.h" #include "EntitiesMP/Bullet.h" #include "EntitiesMP/BackgroundViewer.h" #include "EntitiesMP/SoundHolder.h" #include "GameMP/PlayerSettings.h" #include "ModelsMP/Player/SeriousSam/Player.h" #include "ModelsMP/Player/SeriousSam/Body.h" #include "ModelsMP/Player/SeriousSam/Head.h" extern INDEX ent_bReportBrokenChains; void CCompMessageID::Clear(void) { cmi_fnmFileName.Clear(); cmi_ulHash = 0; } void CCompMessageID::Read_t(CTStream &strm) // throw char * { strm>>cmi_fnmFileName; strm>>(INDEX&)cmi_cmtType; strm>>(INDEX&)cmi_bRead; cmi_ulHash = cmi_fnmFileName.GetHash(); } void CCompMessageID::Write_t(CTStream &strm) // throw char * { strm<GetPlacement().pl_PositionVector; if (pf != NULL) { FLOATmatrix3D mRotation; MakeRotationMatrixFast(mRotation, pen->GetPlacement().pl_OrientationAngle); vPos += FLOAT3D(pf[0], pf[1], pf[2])*mRotation; } }; // get source and target positions for ray cast void GetPositionCastRay(CEntity *penSource, CEntity *penTarget, FLOAT3D &vSource, FLOAT3D &vTarget) { EntityInfo *peiSource = (EntityInfo*) (penSource->GetEntityInfo()); EntityInfo *peiTarget = (EntityInfo*) (penTarget->GetEntityInfo()); ASSERT(peiSource!=NULL && peiTarget!=NULL); // source if (peiSource!=NULL) { GetEntityInfoPosition(penSource, peiSource->vSourceCenter, vSource); } else { vSource = penSource->GetPlacement().pl_PositionVector; } // target if (peiTarget!=NULL) { GetEntityInfoPosition(penTarget, peiTarget->vTargetCenter, vTarget); } else { vTarget = penTarget->GetPlacement().pl_PositionVector; } }; // set bool from bool enum type void SetBoolFromBoolEType(BOOL &bSet, BoolEType bet) { switch (bet) { case BET_TRUE: bSet = TRUE; break; case BET_FALSE: bSet = FALSE; break; //case BET_IGNORE: //bSet = bSet; // break } }; // send event to target void SendToTarget(CEntity *penSendEvent, EventEType eetEventType, CEntity *penCaused) { // if target is valid if (penSendEvent != NULL) { switch (eetEventType) { // send START event case EET_START: { EStart eStart; eStart.penCaused = penCaused; penSendEvent->SendEvent(eStart); } break; // send STOP event case EET_STOP: penSendEvent->SendEvent(EStop()); break; // send TRIGGER event case EET_TRIGGER: { ETrigger eTrigger; eTrigger.penCaused = penCaused; penSendEvent->SendEvent(eTrigger); } break; // don't send event (IGNORE) case EET_IGNORE: break; // send ACTIVATE event case EET_ACTIVATE: penSendEvent->SendEvent(EActivate()); break; // send DEACTIVATE event case EET_DEACTIVATE: penSendEvent->SendEvent(EDeactivate()); break; // send ENVIRONMENTSTART event case EET_ENVIRONMENTSTART: penSendEvent->SendEvent(EEnvironmentStart()); break; // send ENVIRONMENTSTOP event case EET_ENVIRONMENTSTOP: penSendEvent->SendEvent(EEnvironmentStop()); break; // send STARTATTACK event case EET_STARTATTACK: penSendEvent->SendEvent(EStartAttack()); break; // send STOPATTACK event case EET_STOPATTACK: penSendEvent->SendEvent(EStopAttack()); break; case EET_STOPBLINDNESS: penSendEvent->SendEvent(EStopBlindness()); break; case EET_STOPDEAFNESS: penSendEvent->SendEvent(EStopDeafness()); break; case EET_TELEPORTMOVINGBRUSH: penSendEvent->SendEvent(ETeleportMovingBrush()); break; } } }; // send event in range void SendInRange(CEntity *penSource, EventEType eetEventType, const FLOATaabbox3D &boxRange) { switch (eetEventType) { // send START event case EET_START: penSource->SendEventInRange(EStart(), boxRange); break; // send STOP event case EET_STOP: penSource->SendEventInRange(EStop(), boxRange); break; // send TRIGGER event case EET_TRIGGER: penSource->SendEventInRange(ETrigger(), boxRange); break; // don't send event (IGNORE) case EET_IGNORE: break; // send ACTIVATE event case EET_ACTIVATE: penSource->SendEventInRange(EActivate(), boxRange); break; // send DEACTIVATE event case EET_DEACTIVATE: penSource->SendEventInRange(EDeactivate(), boxRange); break; // send ENVIRONMENTSTART event case EET_ENVIRONMENTSTART: penSource->SendEventInRange(EEnvironmentStart(), boxRange); break; // send ENVIRONMENTSTOP event case EET_ENVIRONMENTSTOP: penSource->SendEventInRange(EEnvironmentStop(), boxRange); break; // send STARTATTACK event case EET_STARTATTACK: penSource->SendEventInRange(EStartAttack(), boxRange); break; // send STOPATTACK event case EET_STOPATTACK: penSource->SendEventInRange(EStopAttack(), boxRange); break; case EET_STOPBLINDNESS: penSource->SendEventInRange(EStopBlindness(), boxRange); break; case EET_STOPDEAFNESS: penSource->SendEventInRange(EStopDeafness(), boxRange); break; } }; // spawn reminder CEntityPointer SpawnReminder(CEntity *penOwner, FLOAT fWaitTime, INDEX iValue) { CEntityPointer penReminder; try { penReminder = penOwner->GetWorld()->CreateEntity_t (penOwner->GetPlacement(), CTFILENAME("Classes\\Reminder.ecl")); } catch (char *strError) { FatalError(TRANS("Cannot create reminder entity class: %s"), strError); } EReminderInit eri; eri.penOwner = penOwner; eri.fWaitTime = fWaitTime; eri.iValue = iValue; penReminder->Initialize(eri); return penReminder; }; EffectParticlesType GetParticleEffectTypeForSurface(INDEX iSurfaceType) { EffectParticlesType eptType = EPT_BULLET_STONE; switch( iSurfaceType) { case SURFACE_SAND: {eptType=EPT_BULLET_SAND; break;} case SURFACE_RED_SAND: {eptType=EPT_BULLET_RED_SAND; break;} case SURFACE_WATER: {eptType=EPT_BULLET_WATER; break;} case SURFACE_GRASS: case SURFACE_GRASS_SLIDING: case SURFACE_GRASS_NOIMPACT: {eptType=EPT_BULLET_GRASS; break;} case SURFACE_WOOD: {eptType=EPT_BULLET_WOOD; break;} case SURFACE_SNOW: {eptType=EPT_BULLET_SNOW; break;} } return eptType; } BulletHitType GetBulletHitTypeForSurface(INDEX iSurfaceType) { BulletHitType bhtType = BHT_BRUSH_STONE; switch( iSurfaceType) { case SURFACE_SAND: {bhtType=BHT_BRUSH_SAND; break;} case SURFACE_RED_SAND: {bhtType=BHT_BRUSH_RED_SAND; break;} case SURFACE_WATER: {bhtType=BHT_BRUSH_WATER; break;} case SURFACE_GRASS: case SURFACE_GRASS_SLIDING: case SURFACE_GRASS_NOIMPACT: {bhtType=BHT_BRUSH_GRASS; break;} case SURFACE_WOOD: {bhtType=BHT_BRUSH_WOOD; break;} case SURFACE_SNOW: {bhtType=BHT_BRUSH_SNOW; break;} } return bhtType; } // spawn effect from hit type void SpawnHitTypeEffect(CEntity *pen, enum BulletHitType bhtType, BOOL bSound, FLOAT3D vHitNormal, FLOAT3D vHitPoint, FLOAT3D vIncommingBulletDir, FLOAT3D vDistance) { switch (bhtType) { case BHT_BRUSH_STONE: case BHT_BRUSH_SAND: case BHT_BRUSH_RED_SAND: case BHT_BRUSH_WATER: case BHT_BRUSH_UNDER_WATER: case BHT_BRUSH_GRASS: case BHT_BRUSH_WOOD: case BHT_BRUSH_SNOW: { // bullet stain ESpawnEffect ese; if( bSound) { if( bhtType == BHT_BRUSH_STONE) {ese.betType = BET_BULLETSTAINSTONE;}; if( bhtType == BHT_BRUSH_SAND) {ese.betType = BET_BULLETSTAINSAND;}; if( bhtType == BHT_BRUSH_RED_SAND) {ese.betType = BET_BULLETSTAINREDSAND;}; if( bhtType == BHT_BRUSH_WATER) {ese.betType = BET_BULLETSTAINWATER;}; if( bhtType == BHT_BRUSH_UNDER_WATER) {ese.betType = BET_BULLETSTAINUNDERWATER;}; if( bhtType == BHT_BRUSH_GRASS) {ese.betType = BET_BULLETSTAINGRASS;}; if( bhtType == BHT_BRUSH_WOOD) {ese.betType = BET_BULLETSTAINWOOD;}; if( bhtType == BHT_BRUSH_SNOW) {ese.betType = BET_BULLETSTAINSNOW;}; } else { if( bhtType == BHT_BRUSH_STONE) {ese.betType = BET_BULLETSTAINSTONENOSOUND;}; if( bhtType == BHT_BRUSH_SAND) {ese.betType = BET_BULLETSTAINSANDNOSOUND;}; if( bhtType == BHT_BRUSH_RED_SAND) {ese.betType = BET_BULLETSTAINREDSANDNOSOUND;}; if( bhtType == BHT_BRUSH_WATER) {ese.betType = BET_BULLETSTAINWATERNOSOUND;}; if( bhtType == BHT_BRUSH_UNDER_WATER) {ese.betType = BET_BULLETSTAINUNDERWATERNOSOUND;}; if( bhtType == BHT_BRUSH_GRASS) {ese.betType = BET_BULLETSTAINGRASSNOSOUND;}; if( bhtType == BHT_BRUSH_WOOD) {ese.betType = BET_BULLETSTAINWOODNOSOUND;}; if( bhtType == BHT_BRUSH_SNOW) {ese.betType = BET_BULLETSTAINSNOWNOSOUND;}; } ese.vNormal = vHitNormal; ese.colMuliplier = C_WHITE|CT_OPAQUE; // reflect direction arround normal FLOAT fNx = vHitNormal(1); FLOAT fNy = vHitNormal(2); FLOAT fNz = vHitNormal(3); FLOAT fNV = fNx*vIncommingBulletDir(1) + fNy*vIncommingBulletDir(2) + fNz*vIncommingBulletDir(3); FLOAT fRVx = vIncommingBulletDir(1) - 2*fNx*fNV; FLOAT fRVy = vIncommingBulletDir(2) - 2*fNy*fNV; FLOAT fRVz = vIncommingBulletDir(3) - 2*fNz*fNV; ese.vStretch = FLOAT3D( fRVx, fRVy, fRVz); try { // spawn effect CPlacement3D plHit = CPlacement3D(vHitPoint-vIncommingBulletDir*0.1f, pen->GetPlacement().pl_OrientationAngle); CEntityPointer penHit = pen->GetWorld()->CreateEntity_t(plHit , CTFILENAME("Classes\\BasicEffect.ecl")); penHit->Initialize(ese); } catch (char *strError) { FatalError(TRANS("Cannot create basic effect class: %s"), strError); } break; } case BHT_FLESH: case BHT_ACID: { // spawn bullet entry wound ESpawnEffect ese; ese.colMuliplier = C_WHITE|CT_OPAQUE; // if there is exit wound blood spill place FLOAT fDistance = vDistance.Length(); if( fDistance>0.01f && !(pen->IRnd()%2) ) { // spawn bullet exit wound blood patch ese.betType = BET_BLOODSPILL; if( bhtType == BHT_ACID) { ese.colMuliplier = BLOOD_SPILL_GREEN; } else { ese.colMuliplier = BLOOD_SPILL_RED; } ese.vNormal = vHitNormal; if (fDistance<25.0f) { GetNormalComponent( vDistance/fDistance, vHitNormal, ese.vDirection); FLOAT fLength = ese.vDirection.Length(); fLength = Clamp( fLength*3, 1.0f, 3.0f); fDistance = Clamp( log10(fDistance), 0.5, 2.0); ese.vStretch = FLOAT3D( fDistance, fLength*fDistance, 1.0f); try { // spawn effect CPlacement3D plHit = CPlacement3D(vHitPoint-vIncommingBulletDir*0.1f, pen->GetPlacement().pl_OrientationAngle); CEntityPointer penHit = pen->GetWorld()->CreateEntity_t(plHit , CTFILENAME("Classes\\BasicEffect.ecl")); penHit->Initialize(ese); } catch (char *strError) { FatalError(TRANS("Cannot create basic effect class: %s"), strError); } } } break; } } } // spawn flame CEntityPointer SpawnFlame(CEntity *penOwner, CEntity *penAttach, const FLOAT3D &vSource) { // owner can't flame himself if( penOwner==penAttach) return NULL; FLOAT3D vPos = vSource; // prepare flame event EFlame ef; ef.penOwner = penOwner; ef.penAttach = penAttach; CEntityPointer penFlame; // if the target entity is model if (penAttach->GetRenderType()==CEntity::RT_MODEL || penAttach->GetRenderType()==CEntity::RT_SKAMODEL) { vPos = penAttach->GetPlacement().pl_PositionVector; // if the entity already has a flame attached penFlame = penAttach->GetChildOfClass("Flame"); if (penFlame!=NULL) { // just send it the event penFlame->SendEvent(ef); return penFlame; } } // create new flame try { CPlacement3D plFlame(vPos, ANGLE3D(0, 0, 0)); penFlame = penAttach->GetWorld()->CreateEntity_t(plFlame, CTFILENAME("Classes\\Flame.ecl")); } catch (char *strError) { FatalError(TRANS("Cannot create flame entity class: %s"), strError); } penFlame->Initialize(ef); return penFlame; }; // Kick entity void KickEntity(CEntity *penTarget, FLOAT3D vSpeed) { // if the entity is not allowed to execute now if (!penTarget->IsAllowedForPrediction()) { // do nothing return; } EntityInfo *peiTarget = (EntityInfo*) (penTarget->GetEntityInfo()); if (penTarget->GetPhysicsFlags()&EPF_MOVABLE && peiTarget!=NULL) { // calc new speed acording to target mass vSpeed *= 100.0f/peiTarget->fMass; ((CMovableEntity&)*penTarget).en_vCurrentTranslationAbsolute = vSpeed; ((CMovableEntity&)*penTarget).AddToMovers(); } }; /************************************************************ * SET MODEL AND ATTACHMENT * ************************************************************/ // Set components void SetComponents(CEntity *pen, CModelObject &mo, ULONG ulIDModel, ULONG ulIDTexture, ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) { // model data mo.SetData(pen->GetModelDataForComponent(ulIDModel)); // texture data mo.mo_toTexture.SetData(pen->GetTextureDataForComponent(ulIDTexture)); // reflection texture data if (ulIDReflectionTexture>0) { mo.mo_toReflection.SetData(pen->GetTextureDataForComponent(ulIDReflectionTexture)); } else { mo.mo_toReflection.SetData(NULL); } // specular texture data if (ulIDSpecularTexture>0) { mo.mo_toSpecular.SetData(pen->GetTextureDataForComponent(ulIDSpecularTexture)); } else { mo.mo_toSpecular.SetData(NULL); } // bump texture data if (ulIDBumpTexture>0) { mo.mo_toBump.SetData(pen->GetTextureDataForComponent(ulIDBumpTexture)); } else { mo.mo_toBump.SetData(NULL); } }; // Add attachment to model void AddAttachmentToModel(CEntity *pen, CModelObject &mo, INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture, ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) { SetComponents(pen, mo.AddAttachmentModel(iAttachment)->amo_moModelObject, ulIDModel, ulIDTexture, ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture); }; // Remove attachment from model void RemoveAttachmentFromModel(CModelObject &mo, INDEX iAttachment) { mo.RemoveAttachmentModel(iAttachment); }; /************************************************************ * FLARES * ************************************************************/ // lens flare variables CLensFlareType _lftStandard; CLensFlareType _lftStandardReflections; CLensFlareType _lftYellowStarRedRing; CLensFlareType _lftYellowStarRedRingFar; CLensFlareType _lftWhiteGlowStarRedRing; CLensFlareType _lftWhiteGlowStar; CLensFlareType _lftWhiteGlowStarNG; CLensFlareType _lftWhiteStarRedRingStreaks; CLensFlareType _lftWhiteStarRedReflections; CLensFlareType _lftBlueStarBlueReflections; CLensFlareType _lftProjectileStarGlow; CLensFlareType _lftProjectileWhiteBubbleGlow; CLensFlareType _lftProjectileYellowBubbleGlow; CLensFlareType _lftPVSpaceShipWindowFlare; CLensFlareType _lftCatmanFireGlow; CLensFlareType _lftWhiteGlowFar; static BOOL _bLensFlaresLoaded = FALSE; #define FLARE_CREATE(type,noof,tex,pos,rot,i,j,flags,amp,des,falloff)\ type.lft_aolfFlares.New(noof);\ type.lft_aolfFlares[0].olf_toTexture.SetData_t(CTFILENAME("Textures\\Effects\\Flares\\" tex));\ type.lft_aolfFlares[0].olf_fReflectionPosition = pos;\ type.lft_aolfFlares[0].olf_aRotationFactor = AngleDeg(rot);\ type.lft_aolfFlares[0].olf_fSizeIOverScreenSizeI = i;\ type.lft_aolfFlares[0].olf_fSizeJOverScreenSizeI = j;\ type.lft_aolfFlares[0].olf_ulFlags = flags;\ type.lft_aolfFlares[0].olf_fLightAmplification = amp;\ type.lft_aolfFlares[0].olf_fLightDesaturation = des;\ type.lft_aolfFlares[0].oft_fFallOffFactor = falloff; #define FLARE_GLARE(type,compression,intensity,des,falloff)\ type.lft_fGlareCompression = compression;\ type.lft_fGlareIntensity = intensity;\ type.lft_fGlareDesaturation = des;\ type.lft_fGlareFallOffFactor = falloff; #define REFLECTION(type,i,fnm,pos,size) \ type.lft_aolfFlares[i].olf_toTexture.SetData_t(CTFILENAME("Textures\\Effects\\Flares\\" fnm));\ type.lft_aolfFlares[i].olf_fReflectionPosition = pos;\ type.lft_aolfFlares[i].olf_aRotationFactor = AngleDeg(0.0f);\ type.lft_aolfFlares[i].olf_fSizeIOverScreenSizeI = size;\ type.lft_aolfFlares[i].olf_fSizeJOverScreenSizeI = size;\ type.lft_aolfFlares[i].olf_ulFlags = OLF_FADEINTENSITY|OLF_FADEOFCENTER;\ type.lft_aolfFlares[i].olf_fLightAmplification = 7.0f;\ type.lft_aolfFlares[i].olf_fLightDesaturation = 0.5f;\ type.lft_aolfFlares[i].oft_fFallOffFactor = 5.0f; // init lens flare effects void InitLensFlares(void) { if (_bLensFlaresLoaded) { return; // Player class is not auto-freed, so the engine may attempt to access this function several times } // standard flare FLARE_CREATE(_lftStandard, 1, "01\\WhiteRedRing2.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftStandard, 20.0f, 0.3f, 0.8f, 1.0f); // standard flare with huge reflections FLARE_CREATE(_lftStandardReflections, 15, "01\\WhiteRedRing2.tex", 0.0f, 180.0f, 1.36f, 1.36f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftStandardReflections, 20.0f, 0.3f, 0.8f, 1.0f); REFLECTION(_lftStandardReflections, 1, "01\\WhiteRing.tex", -0.3f, 0.1f); REFLECTION(_lftStandardReflections, 2, "01\\BlueDisc.tex", 1-0.5f, 0.047f); REFLECTION(_lftStandardReflections, 3, "01\\BlueDisc.tex", 1-0.41f, 0.078f); REFLECTION(_lftStandardReflections, 4, "01\\BlueDiscWeak.tex", 1-0.45f, 0.15f); REFLECTION(_lftStandardReflections, 5, "01\\BrownDisc.tex", 1-0.2f, 0.05f); REFLECTION(_lftStandardReflections, 6, "01\\WhiteGradient.tex", 1-0.1f, 0.016f); REFLECTION(_lftStandardReflections, 7, "01\\WhiteGradient.tex", 1+0.29f, 0.027f); REFLECTION(_lftStandardReflections, 8, "01\\BrownDisc.tex", 1+0.5f, 0.05f); REFLECTION(_lftStandardReflections, 9, "01\\BrownDisc.tex", 1+0.43f, 0.11f); REFLECTION(_lftStandardReflections,10, "01\\BrownRing.tex", 1+0.49f, 0.19f); REFLECTION(_lftStandardReflections,11, "01\\BlueDisc.tex", 1+0.68f, 0.08f); REFLECTION(_lftStandardReflections,12, "01\\BlueGradient.tex", 1+0.7f, 0.043f); REFLECTION(_lftStandardReflections,13, "01\\GreenRing.tex", 1+1.04f, 0.27f); REFLECTION(_lftStandardReflections,14, "01\\RainbowRing.tex", 1+1.35f, 0.53f); // nice yellow star with red ring FLARE_CREATE(_lftYellowStarRedRing, 1, "02\\Flare05.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftYellowStarRedRing, 20.0f, 0.3f, 0.8f, 1.0f); // same yellow star with red ring but visible from far away FLARE_CREATE(_lftYellowStarRedRingFar, 1, "02\\Flare05.tex", 0.0f, 180.0f, 1/12.0f, 1/12.0f, OLF_FADESIZE, 0.25f, 0.5f, 128.0f); FLARE_GLARE(_lftYellowStarRedRingFar, 20.0f, 0.3f, 0.8f, 1.0f); // nice yellow star with red ring FLARE_CREATE(_lftWhiteGlowStarRedRing, 1, "03\\Flare06.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftWhiteGlowStarRedRing, 20.0f, 0.3f, 0.8f, 1.0f); FLARE_CREATE(_lftWhiteGlowStar, 1, "04\\Flare07.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftWhiteGlowStar, 20.0f, 0.3f, 0.8f, 1.0f); FLARE_CREATE(_lftWhiteGlowStarNG, 1, "04\\Flare07.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_CREATE(_lftWhiteStarRedRingStreaks, 1, "05\\Flare09.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftWhiteStarRedRingStreaks, 20.0f, 0.3f, 0.8f, 1.0f); // white star flare with many red and brown hexagons FLARE_CREATE(_lftWhiteStarRedReflections, 12, "06\\WhiteStarManyStreaks.tex", 0.0f, 0.0f, 0.20625f, 0.20625f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftWhiteStarRedReflections, 20.0f, 0.3f, 0.8f, 1.0f); REFLECTION(_lftWhiteStarRedReflections, 1, "06\\DarkRedPentagram.tex" ,-0.92424242f,0.06875f); REFLECTION(_lftWhiteStarRedReflections, 2, "06\\LillaPentagram.tex" ,0.28787879f,0.0296875f); REFLECTION(_lftWhiteStarRedReflections, 3, "06\\MagentaPentagram.tex" ,0.43939394f,0.05f); REFLECTION(_lftWhiteStarRedReflections, 4, "06\\MagentaGlow.tex" ,1.52272727f,0.009375f); REFLECTION(_lftWhiteStarRedReflections, 5, "06\\DarkRedPentagram.tex" ,1.9469697f,0.06875f); REFLECTION(_lftWhiteStarRedReflections, 6, "06\\MagentaGlow.tex" ,1.96212121f,0.05f); REFLECTION(_lftWhiteStarRedReflections, 7, "06\\DarkRedPentagram.tex" ,1.08333333f,0.06875f); REFLECTION(_lftWhiteStarRedReflections, 8, "06\\DarkRedPentagram.tex" ,1.59848485f,0.06875f); REFLECTION(_lftWhiteStarRedReflections, 9, "06\\DarkRedPentagram.tex" ,1.67424242f,0.06875f); REFLECTION(_lftWhiteStarRedReflections,10, "06\\DarkRedPentagram.tex" ,-0.12878788f,0.03125f); REFLECTION(_lftWhiteStarRedReflections,11, "06\\BrownPentagram.tex" ,0.03030303f,0.021875f); // blue star flare with many blue flares FLARE_CREATE(_lftBlueStarBlueReflections, 21, "07\\BlueStarManyStreaks.tex", 0.0f, 0.0f, 0.4f, 0.4f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); FLARE_GLARE(_lftBlueStarBlueReflections, 20.0f, 0.3f, 0.8f, 1.0f); REFLECTION(_lftBlueStarBlueReflections, 1, "07\\BlueGlow.tex", -0.5f,0.05f); REFLECTION(_lftBlueStarBlueReflections, 2, "07\\BluePentagram.tex", -0.25f,0.03f); REFLECTION(_lftBlueStarBlueReflections, 3, "07\\GreenGlow.tex", -0.05f,0.04f); REFLECTION(_lftBlueStarBlueReflections, 4, "07\\GreenGlow.tex", 0.3f,0.02f); REFLECTION(_lftBlueStarBlueReflections, 5, "07\\BluePentagram.tex", 0.5f,0.05f); REFLECTION(_lftBlueStarBlueReflections, 6, "07\\DarkBluePentagram.tex", 0.8f,0.04f); REFLECTION(_lftBlueStarBlueReflections, 7, "07\\LittleBluePentagram.tex", 1.2f,0.02f); REFLECTION(_lftBlueStarBlueReflections, 8, "07\\MagentaPentagram.tex", 1.13f,0.08f); REFLECTION(_lftBlueStarBlueReflections, 9, "07\\DarkBluePentagram.tex", 1.24f,0.03f); REFLECTION(_lftBlueStarBlueReflections,10, "07\\BlueGlow.tex", 1.4f,0.06f); REFLECTION(_lftBlueStarBlueReflections,11, "07\\GreenGlow.tex", 1.5f,0.02f); REFLECTION(_lftBlueStarBlueReflections,12, "07\\BluePentagram.tex", 1.64f,0.05f); REFLECTION(_lftBlueStarBlueReflections,13, "07\\LittleBluePentagram.tex", 1.7f,0.05f); REFLECTION(_lftBlueStarBlueReflections,14, "07\\BluePentagram.tex", 1.8f,0.06f); REFLECTION(_lftBlueStarBlueReflections,15, "07\\MagentaPentagram.tex", 2.0f,0.01f); REFLECTION(_lftBlueStarBlueReflections,16, "07\\BlueGlow.tex", 2.0f,0.06f); REFLECTION(_lftBlueStarBlueReflections,17, "07\\MagentaPentagram.tex", 2.0f,0.02f); REFLECTION(_lftBlueStarBlueReflections,18, "07\\GreenGlow.tex", 2.1f,0.015f); REFLECTION(_lftBlueStarBlueReflections,19, "07\\BluePentagram.tex", 2.4f,0.05f); REFLECTION(_lftBlueStarBlueReflections,20, "07\\DarkBluePentagram.tex", 2.8f,0.03f); FLARE_CREATE(_lftProjectileStarGlow, 1, "08\\FlarePower.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 10.0f); FLARE_GLARE(_lftProjectileStarGlow, 20.0f, 0.3f, 0.8f, 1.0f); FLARE_CREATE(_lftProjectileWhiteBubbleGlow, 1, "09\\FlareWhiteBubble.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 10.0f); FLARE_GLARE(_lftProjectileWhiteBubbleGlow, 20.0f, 0.3f, 0.8f, 1.0f); FLARE_CREATE(_lftProjectileYellowBubbleGlow, 1, "10\\FlareYellowBubble.tex", 0.0f, 180.0f, 1/10.0f, 1/10.0f, OLF_FADESIZE, 7.0f, 0.5f, 10.0f); FLARE_GLARE(_lftProjectileYellowBubbleGlow, 20.0f, 0.3f, 0.8f, 1.0f); FLARE_CREATE(_lftPVSpaceShipWindowFlare, 1, "05\\Flare09.tex", 0.0f, 180.0f, 1/10.0f, 1/10.0f, OLF_FADESIZE, 1.0f, 0.0f, 10.0f); FLARE_CREATE(_lftCatmanFireGlow, 1, "12\\Flare12.tex", 0.0f, 180.0f, 1/12.0f, 1/12.0f, OLF_FADESIZE, 7.0f, 0.5f, 128.0f); FLARE_CREATE(_lftWhiteGlowFar, 1, "13\\Flare13.tex", 0.0f, 180.0f, 1/16.0f, 1/16.0f, OLF_FADESIZE, 7.0f, 0.5f, 128.0f); _bLensFlaresLoaded = TRUE; }; // close lens flares effects void CloseLensFlares(void) { _lftStandard.lft_aolfFlares.Clear(); _lftStandardReflections.lft_aolfFlares.Clear(); _lftYellowStarRedRing.lft_aolfFlares.Clear(); _lftYellowStarRedRingFar.lft_aolfFlares.Clear(); _lftWhiteGlowStarRedRing.lft_aolfFlares.Clear(); _lftWhiteGlowStar.lft_aolfFlares.Clear(); _lftWhiteGlowStarNG.lft_aolfFlares.Clear(); _lftWhiteStarRedRingStreaks.lft_aolfFlares.Clear(); _lftWhiteStarRedReflections.lft_aolfFlares.Clear(); _lftBlueStarBlueReflections.lft_aolfFlares.Clear(); _lftProjectileStarGlow.lft_aolfFlares.Clear(); _lftProjectileWhiteBubbleGlow.lft_aolfFlares.Clear(); _lftProjectileYellowBubbleGlow.lft_aolfFlares.Clear(); _lftPVSpaceShipWindowFlare.lft_aolfFlares.Clear(); _lftCatmanFireGlow.lft_aolfFlares.Clear(); _lftWhiteGlowFar.lft_aolfFlares.Clear(); _bLensFlaresLoaded = FALSE; }; static BOOL _bFatalChecks = FALSE; /************************************************************ * PLAYER APPEARANCE * ************************************************************/ /* Set the model data */ void SetModelData_t(CModelObject *pmo, const CTFileName &fnmModel) { ASSERT(pmo != NULL); pmo->SetData_t(fnmModel); // load the new model data }; /* Set the texture data */ void SetTextureData_t(CModelObject *pmo, const CTFileName &fnmTexture) { ASSERT(pmo != NULL); pmo->mo_toTexture.SetData_t(fnmTexture); // load the texture data }; /* Set model */ void SetModel_t(CModelObject *pmo, const CTFileName &fnmModel, const CTFileName &fnmTexture) { SetModelData_t(pmo, fnmModel); SetTextureData_t(pmo, fnmTexture); }; /* Add attachment to model */ void ModelAddAttachment_t(CModelObject *pmo, INDEX iAttachment, const CTFileName &fnmModel, const CTFileName &fnmTexture) { ASSERT(pmo != NULL); if (fnmModel==CTString("")) return; if (pmo==NULL) return; CAttachmentModelObject *pamo = pmo->AddAttachmentModel(iAttachment); SetModel_t(&(pamo->amo_moModelObject), fnmModel, fnmTexture); }; CTString _strFile; INDEX _ctLines; CTString GetNonEmptyLine_t(CTStream &strm) { FOREVER { if(strm.AtEOF()) { ThrowF_t(TRANS("Unexpected end of file")); } CTString str; _ctLines++; strm.GetLine_t(str); str.TrimSpacesLeft(); if (str.RemovePrefix("//")) { // skip comments continue; } if (str!="") { str.TrimSpacesRight(); return str; } } } void FixupFileName_t(CTString &strFnm) { strFnm.TrimSpacesLeft(); if (!strFnm.RemovePrefix(CTString("TF") +"NM ")) { // must not directly have ids in code ThrowF_t(TRANS("Expected %s%s before filename"), "TF", "NM"); } } // skip one block in pmc void SkipBlock_t(CTStream &strm) { CTString strLine; // expect to begin with an open bracket strLine = GetNonEmptyLine_t(strm); if (strLine!="{") { ThrowF_t(TRANS("Expected '{'")); } // start at level one INDEX ctLevel = 1; // repeat do { strLine = GetNonEmptyLine_t(strm); // count brackets if (strLine=="{") { ctLevel++; } else if (strLine=="}") { ctLevel--; } // until we close down all brackets } while(ctLevel>0); } void ParseAMC_t(CModelObject *pmo, CTStream &strm, BOOL bPreview) { CTString strLine; // expect to begin with an open bracket strLine = GetNonEmptyLine_t(strm); if (strLine!="{") { ThrowF_t(TRANS("Expected '{'")); } // repeat FOREVER { // read one line strLine = GetNonEmptyLine_t(strm); // if closed bracket if (strLine == "}") { // finish parsing return; } // if a preview-only block if (strLine.RemovePrefix("PreviewOnly")) { // if this is a preview if (bPreview) { // keep parsing it ParseAMC_t(pmo, strm, bPreview); // if this is not a preview } else { // skip that block SkipBlock_t(strm); } // if include block } else if (strLine.RemovePrefix("Include:")) { // open the new file FixupFileName_t(strLine); CTFileStream strmIncluded; strmIncluded.Open_t(strLine); // include it INDEX ctLinesOld = _ctLines; CTString strFileOld = _strFile; _ctLines = 0; _strFile = strLine; ParseAMC_t(pmo, strmIncluded, bPreview); strmIncluded.Close(); _ctLines = ctLinesOld; _strFile = strFileOld; // if setting the model } else if (strLine.RemovePrefix("Model:")) { // set the model FixupFileName_t(strLine); pmo->SetData_t(strLine); // if setting an anim for the model } else if (strLine.RemovePrefix("Animation:")) { // get animation number INDEX iAnim = -1; strLine.ScanF("%d", &iAnim); if (iAnim<0) { ThrowF_t(TRANS("Invalid animation number")); } // check it if (iAnim>=pmo->GetAnimsCt()) { ThrowF_t(TRANS("Animation %d does not exist in that model"), iAnim); }; // set it pmo->PlayAnim(iAnim, AOF_LOOPING); // if texture } else if (strLine.RemovePrefix("Texture:")) { // set texture FixupFileName_t(strLine); pmo->mo_toTexture.SetData_t(strLine); // if specular } else if (strLine.RemovePrefix("Specular:")) { // set texture FixupFileName_t(strLine); pmo->mo_toSpecular.SetData_t(strLine); // if reflection } else if (strLine.RemovePrefix("Reflection:")) { // set texture FixupFileName_t(strLine); pmo->mo_toReflection.SetData_t(strLine); // if specular } else if (strLine.RemovePrefix("Bump:")) { // set texture FixupFileName_t(strLine); pmo->mo_toBump.SetData_t(strLine); // if attachment } else if (strLine.RemovePrefix("Attachment:")) { // get attachment number INDEX iAtt = -1; strLine.ScanF("%d", &iAtt); if (iAtt<0) { ThrowF_t(TRANS("Invalid attachment number")); } // create attachment CModelData *pmd = (CModelData*)pmo->GetData(); if (iAtt>=pmd->md_aampAttachedPosition.Count()) { ThrowF_t(TRANS("Attachment %d does not exist in that model"), iAtt); }; CAttachmentModelObject *pamo = pmo->AddAttachmentModel(iAtt); // recursively parse it ParseAMC_t(&pamo->amo_moModelObject, strm, bPreview); } else { ThrowF_t(TRANS("Expected texture or attachment")); } } } /* Set player appearance */ BOOL SetPlayerAppearance_internal(CModelObject *pmo, const CTFileName &fnmAMC, CTString &strName, BOOL bPreview) { // try to try { // open the config file CTFileStream strm; strm.Open_t(fnmAMC); _ctLines = 0; _strFile = fnmAMC; // read the name CTString strLine = GetNonEmptyLine_t(strm); if (!strLine.RemovePrefix("Name: ")) { ThrowF_t(TRANS("Expected name")); } strName = strLine; strName.TrimSpacesLeft(); // parse the file recursively starting at root model object and add everything ParseAMC_t(pmo, strm, bPreview); return TRUE; // if anything failed } catch (char *strError) { // report error CPrintF(TRANSV("Cannot load player model:\n%s (%d) : %s\n"), (const char*)_strFile, _ctLines, strError); return FALSE; } } BOOL SetPlayerAppearance(CModelObject *pmo, CPlayerCharacter *ppc, CTString &strName, BOOL bPreview) { // first kill any existing model pmo->SetData(NULL); pmo->mo_toTexture.SetData(NULL); pmo->mo_toSpecular.SetData(NULL); pmo->mo_toReflection.SetData(NULL); pmo->mo_toBump.SetData(NULL); pmo->RemoveAllAttachmentModels(); DECLARE_CTFILENAME(fnmDefault, "ModelsMP\\Player\\SeriousSam.amc"); // if no character, or player models are disabled if (ppc==NULL) { // set default appearance BOOL bSucceeded = SetPlayerAppearance_internal(pmo, fnmDefault, strName, bPreview); if (!bSucceeded) { FatalError(TRANS("Cannot load default player model!")); } return FALSE; } // get filename from the settings CPlayerSettings *pps = (CPlayerSettings *)ppc->pc_aubAppearance; CTFileName fnmModelFile = pps->GetModelFilename(); // if dummy (empty settings) if (fnmModelFile.FileName()=="") { // use default fnmModelFile = fnmDefault; } extern INDEX plr_bOnlySam; if (!plr_bOnlySam && SetPlayerAppearance_internal(pmo, fnmModelFile, strName, bPreview)) { return TRUE; } else if (SetPlayerAppearance_internal(pmo, fnmDefault, strName, bPreview)) { // HAVE TO SET DEFAULT HERE! return TRUE; } else { return FALSE; } } /************************************************************ * DEBUGGING FUNCTIONS * ************************************************************/ // debugging functions const char *PrintConsole(void) { _RPT1(_CRT_WARN, "%s", CON_GetBuffer()); return NULL; } const char *PrintStack(CEntity *pen) { return pen->PrintStackDebug(); } /************************************************************ * DEBRIS * ************************************************************/ EntityInfoBodyType _Eeibt; enum DebrisParticlesType _dptParticles; enum BasicEffectType _betStain; FLOAT3D _vSpeed; FLOAT3D _vSpawnerSpeed; FLOAT _fEntitySize; FLOAT _fConeSize; FLOAT _fSpeedUp; COLOR _colDebris; // debris spawning void Debris_Begin( EntityInfoBodyType Eeibt, int /*enum DebrisParticlesType*/ _dptParticles, int /*enum BasicEffectType*/ _betStain, FLOAT fEntitySize, // entity size in meters const FLOAT3D &vSpeed, const FLOAT3D &vSpawnerSpeed, // how fast was the entity moving const FLOAT fConeSize, // size multiplier for debris cone const FLOAT fSpeedUp, // size multiplier for debris catapulting up (0-no multiply) const COLOR colDebris /*=C_WHITE*/ // multiply color ) { enum DebrisParticlesType dptParticles = (enum DebrisParticlesType) _dptParticles; enum BasicEffectType betStain = (enum BasicEffectType) _betStain; _Eeibt = Eeibt ; _dptParticles = dptParticles; _betStain = betStain ; _vSpeed = vSpeed ; _vSpawnerSpeed = vSpawnerSpeed; _fEntitySize = fEntitySize ; _fConeSize = fConeSize ; _fSpeedUp = fSpeedUp ; _colDebris = colDebris ; } CEntityPointer Debris_Spawn( CEntity *penSpawner, CEntity *penComponents, SLONG idModelComponent, SLONG idTextureComponent, SLONG idReflectionTextureComponent, SLONG idSpecularTextureComponent, SLONG idBumpTextureComponent, INDEX iModelAnim, FLOAT fSize, const FLOAT3D &vPosRatio) { // create debris at same world as spawner FLOAT3D vPos; FLOAT3D vStretch=FLOAT3D(1,1,1); if( (penSpawner->en_RenderType==CEntity::RT_MODEL || penSpawner->en_RenderType==CEntity::RT_EDITORMODEL) && penSpawner->GetModelObject()!=NULL) { vStretch=penSpawner->GetModelObject()->mo_Stretch; } penSpawner->GetEntityPointRatio(vPosRatio, vPos); CEntityPointer penDebris = penSpawner->GetWorld()->CreateEntity_t( CPlacement3D(vPos, ANGLE3D(0,0,0)), CTFILENAME("Classes\\Debris.ecl")); // prepare parameters ESpawnDebris eSpawn; eSpawn.bImmaterialASAP=FALSE; eSpawn.bCustomShading=FALSE; eSpawn.Eeibt = _Eeibt; eSpawn.dptParticles = _dptParticles; eSpawn.betStain = _betStain; eSpawn.pmd = penComponents->GetModelDataForComponent(idModelComponent); eSpawn.ptd = penComponents->GetTextureDataForComponent(idTextureComponent); eSpawn.ptdRefl = penComponents->GetTextureDataForComponent(idReflectionTextureComponent); eSpawn.ptdSpec = penComponents->GetTextureDataForComponent(idSpecularTextureComponent); eSpawn.ptdBump = penComponents->GetTextureDataForComponent(idBumpTextureComponent); eSpawn.iModelAnim = iModelAnim; eSpawn.colDebris = _colDebris; eSpawn.vStretch = FLOAT3D(1,1,1); if (fSize==0) { eSpawn.fSize = 1.0f; } else { eSpawn.fSize = _fEntitySize*fSize; } // initialize it penDebris->Initialize(eSpawn); FLOAT fCone = _fEntitySize*1.0f; if (_vSpeed.Length()==0) { fCone = 0; } FLOAT fRndX = (penSpawner->FRnd()*2-1)*fCone*_fConeSize; FLOAT fRndY = (penSpawner->FRnd()*2-1)*fCone*_fConeSize; FLOAT fRndZ = (penSpawner->FRnd()*2-1)*fCone*_fConeSize; FLOAT fRndH = penSpawner->FRnd(); FLOAT fRndP = penSpawner->FRnd(); FLOAT fRndB = penSpawner->FRnd(); FLOAT3D vUp; const FLOATmatrix3D &m = penSpawner->GetRotationMatrix(); vUp(1) = m(1,2); vUp(2) = m(2,2); vUp(3) = m(3,2); //FLOAT fStrength = _vSpeed.Length(); // speed it up ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( _vSpawnerSpeed+_vSpeed+FLOAT3D(fRndX, fRndY, fRndZ)+vUp*_fSpeedUp, (CMovableEntity*)penSpawner); ((CMovableEntity&)*penDebris).SetDesiredRotation( ANGLE3D(fRndH*360.0f-180.0f, fRndP*360.0f-180.0f, fRndB*360.0f-180.0f)); return penDebris; } CEntityPointer Debris_Spawn_Independent( CEntity *penSpawner, CEntity *penComponents, SLONG idModelComponent, SLONG idTextureComponent, SLONG idReflectionTextureComponent, SLONG idSpecularTextureComponent, SLONG idBumpTextureComponent, INDEX iModelAnim, FLOAT fSize, CPlacement3D plAbsolutePlacement, FLOAT3D vTranslation, ANGLE3D aRotation) { // create debris at same world as spawner CEntityPointer penDebris = penSpawner->GetWorld()->CreateEntity_t( plAbsolutePlacement, CTFILENAME("Classes\\Debris.ecl")); // prepare parameters ESpawnDebris eSpawn; eSpawn.bImmaterialASAP=FALSE; eSpawn.bCustomShading=FALSE; eSpawn.Eeibt = _Eeibt; eSpawn.dptParticles = _dptParticles; eSpawn.betStain = _betStain; eSpawn.pmd = penComponents->GetModelDataForComponent(idModelComponent); eSpawn.ptd = penComponents->GetTextureDataForComponent(idTextureComponent); eSpawn.ptdRefl = penComponents->GetTextureDataForComponent(idReflectionTextureComponent); eSpawn.ptdSpec = penComponents->GetTextureDataForComponent(idSpecularTextureComponent); eSpawn.ptdBump = penComponents->GetTextureDataForComponent(idBumpTextureComponent); eSpawn.iModelAnim = iModelAnim; eSpawn.colDebris = _colDebris; eSpawn.fSize = fSize; eSpawn.vStretch = FLOAT3D(1,1,1); // initialize it penDebris->Initialize(eSpawn); // move it ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vTranslation, (CMovableEntity*)penSpawner); ((CMovableEntity&)*penDebris).SetDesiredRotation(aRotation); return penDebris; } CEntityPointer Debris_Spawn_Template( EntityInfoBodyType eibt, int /*enum DebrisParticlesType*/ _dptParticles, int /*enum BasicEffectType*/ _betStain, CModelHolder2 *penmhDestroyed, CEntity *penComponents, CModelHolder2 *penmhTemplate, FLOAT3D vStretch, FLOAT fSize, CPlacement3D plAbsolutePlacement, FLOAT3D vLaunchSpeed, ANGLE3D aRotSpeed, BOOL bDebrisImmaterialASAP, FLOAT fDustStretch, COLOR colBurning) { enum DebrisParticlesType dptParticles = (enum DebrisParticlesType) _dptParticles; enum BasicEffectType betStain = (enum BasicEffectType) _betStain; if(penmhTemplate==NULL || penmhTemplate->GetModelObject()==NULL) { return NULL; } // create debris at same world as spawner CEntityPointer penDebris = penmhDestroyed->GetWorld()->CreateEntity_t( plAbsolutePlacement, CTFILENAME("Classes\\Debris.ecl")); // prepare parameters ESpawnDebris eSpawn; eSpawn.bImmaterialASAP=bDebrisImmaterialASAP; eSpawn.fDustStretch=fDustStretch; eSpawn.Eeibt = eibt; eSpawn.dptParticles = dptParticles; eSpawn.betStain = betStain; CModelObject &mo=*penmhTemplate->GetModelObject(); eSpawn.pmd = mo.GetData(); eSpawn.ptd = (CTextureData*)mo.mo_toTexture.GetData(); eSpawn.ptdRefl = (CTextureData*)mo.mo_toReflection.GetData(); eSpawn.ptdSpec = (CTextureData*)mo.mo_toSpecular.GetData(); eSpawn.ptdBump = (CTextureData*)mo.mo_toBump.GetData(); eSpawn.iModelAnim = mo.GetAnim(); eSpawn.colDebris = colBurning; eSpawn.fSize = 1.0f; eSpawn.vStretch = vStretch; eSpawn.bCustomShading=FALSE; eSpawn.penFallFXPapa=penmhTemplate; if( penmhDestroyed->m_cstCustomShading==CST_FULL_CUSTOMIZED) { eSpawn.bCustomShading=TRUE; eSpawn.aShadingDirection=penmhDestroyed->m_aShadingDirection; eSpawn.colCustomDiffuse=penmhDestroyed->m_colLight; eSpawn.colCustomAmbient=penmhDestroyed->m_colAmbient; } // initialize it penDebris->Initialize(eSpawn); // move it const FLOATmatrix3D &m = penDebris->GetRotationMatrix(); ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vLaunchSpeed*!m, (CMovableEntity*)penmhDestroyed); ((CMovableEntity&)*penDebris).SetDesiredRotation(aRotSpeed); return penDebris; } // info structure static EntityInfo eiFlesh = {EIBT_FLESH}; static EntityInfo eiWater = {EIBT_WATER}; static EntityInfo eiRock = {EIBT_ROCK }; static EntityInfo eiFire = {EIBT_FIRE }; static EntityInfo eiAir = {EIBT_AIR }; static EntityInfo eiBones = {EIBT_BONES}; static EntityInfo eiWood = {EIBT_WOOD }; static EntityInfo eiMetal = {EIBT_METAL}; static EntityInfo eiRobot = {EIBT_ROBOT}; static EntityInfo eiIce = {EIBT_ICE }; // get default entity info for given body type EntityInfo *GetStdEntityInfo(EntityInfoBodyType eibt) { switch(eibt) { case EIBT_FLESH: {return &eiFlesh; } break; case EIBT_WATER: {return &eiWater; } break; case EIBT_ROCK : {return &eiRock ; } break; case EIBT_FIRE : {return &eiFire ; } break; case EIBT_AIR : {return &eiAir ; } break; case EIBT_BONES: {return &eiBones; } break; case EIBT_WOOD : {return &eiWood ; } break; case EIBT_METAL: {return &eiMetal; } break; case EIBT_ROBOT: {return &eiRobot; } break; case EIBT_ICE : {return &eiIce ; } break; default: {return NULL;} break; }; } /************************************************************ * DAMAGE CONTROL FUNCTIONS * ************************************************************/ // damage control functions FLOAT DamageStrength(EntityInfoBodyType eibtBody, enum DamageType dtDamage) { switch(eibtBody) { case EIBT_FLESH: return 1.0f; case EIBT_WATER: switch(dtDamage) { case DMT_CLOSERANGE: return 0.0f; case DMT_BURNING: return 0.0f; case DMT_DROWNING: return 0.0f; } return 1.0f; case EIBT_ROCK : switch(dtDamage) { case DMT_CLOSERANGE: return 0.0f; case DMT_BURNING: return 0.0f; case DMT_FREEZING: return 0.0f; } return 1.0f; case EIBT_ICE : switch(dtDamage) { case DMT_CLOSERANGE: return 0.5f; case DMT_BURNING: return 3.0f; case DMT_FREEZING: return 0.0f; } return 1.0f; case EIBT_FIRE : switch(dtDamage) { case DMT_CLOSERANGE: return 0.5f; case DMT_BURNING: return 0.0f; } return 1.0f; case EIBT_AIR : switch(dtDamage) { case DMT_CLOSERANGE: return 0.0f; case DMT_BURNING: return 0.5f; } return 1.0f; case EIBT_BONES: switch(dtDamage) { case DMT_FREEZING: return 0.0f; } return 1.0f; case EIBT_WOOD : switch(dtDamage) { case DMT_FREEZING: return 0.0f; } return 1.0f; case EIBT_METAL: switch(dtDamage) { case DMT_CLOSERANGE: return 0.0f; case DMT_BURNING: return 0.0f; case DMT_FREEZING: return 0.0f; } return 1.0f; case EIBT_ROBOT: switch(dtDamage) { case DMT_CLOSERANGE:return 0.5f; case DMT_BURNING: return 0.5f; case DMT_FREEZING: return 0.5f; } return 1.0f; default: ASSERT(FALSE); return 1.0f; } } // Print center screen message void PrintCenterMessage(CEntity *penThis, CEntity *penCaused, const CTString &strMessage, TIME tmLength, enum MessageSound mssSound) { penCaused = FixupCausedToPlayer(penThis, penCaused); ECenterMessage eMsg; eMsg.strMessage = strMessage; eMsg.tmLength = tmLength; eMsg.mssSound = mssSound; penCaused->SendEvent(eMsg); } // i.e. weapon sound when fireing or exploding void SpawnRangeSound( CEntity *penPlayer, CEntity *penPos, enum SoundType st, FLOAT fRange) { // if not really player if (!IsDerivedFromClass(penPlayer, "Player")) { // do nothing return; } // sound event ESound eSound; eSound.EsndtSound = st; eSound.penTarget = penPlayer; penPos->SendEventInRange( eSound, FLOATaabbox3D(penPos->GetPlacement().pl_PositionVector, fRange)); } // get some player for trigger source if any is existing CEntity *FixupCausedToPlayer(CEntity *penThis, CEntity *penCaused, BOOL bWarning/*=TRUE*/) { if (penCaused!=NULL && IsOfClass(penCaused, "Player")) { return penCaused; } if (bWarning && (ent_bReportBrokenChains || GetSP()->sp_bQuickTest)) { CPrintF(TRANSV("WARNING: Triggering chain broken, entity: %s-%s(%s)\n"), (const char*)penThis->GetName(), (const char*)penThis->GetDescription(), (const char*)penThis->GetClass()->GetName()); } INDEX ctPlayers = penThis->GetMaxPlayers(); if (ctPlayers==0) { return NULL; } CEntity *penClosestPlayer = NULL; FLOAT fClosestPlayer = UpperLimit(0.0f); // for all players for (INDEX iPlayer=0; iPlayerGetMaxPlayers(); iPlayer++) { CEntity *penPlayer = penThis->GetPlayerEntity(iPlayer); // if player exists if (penPlayer!=NULL) { // calculate distance to player FLOAT fDistance = (penPlayer->GetPlacement().pl_PositionVector-penThis->GetPlacement().pl_PositionVector).Length(); // update if closer if (fDistancesp_fExtraEnemyStrength; if (fExtraStrength>0) { fGameDamageMultiplier*=1.0f/(1+fExtraStrength); } FLOAT fExtraStrengthPerPlayer = GetSP()->sp_fExtraEnemyStrengthPerPlayer; if (fExtraStrengthPerPlayer>0) { INDEX ctPlayers = _pNetwork->ga_sesSessionState.GetPlayersCount(); fGameDamageMultiplier*=1.0f/(1+fExtraStrengthPerPlayer*ClampDn(((FLOAT) ctPlayers)-1.0f, 0.0f)); } if (GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_TOURIST) { fGameDamageMultiplier *= 2.0f; } return fGameDamageMultiplier; } // get entity's serious damage multiplier FLOAT GetSeriousDamageMultiplier( CEntity *pen) { if( !IsOfClass(pen,"Player")) return 1.0f; const TIME tmNow = _pTimer->CurrentTick(); const TIME tmDamage = ((CPlayer*)pen)->m_tmSeriousDamage; if( tmDamage>tmNow) return 4.0f; return 1.0f; } class CWorldSettingsController *GetWSC(CEntity *pen) { CWorldSettingsController *pwsc = NULL; // obtain bcg viewer class CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) pen->GetWorld()->GetBackgroundViewer(); if( penBcgViewer != NULL) { // obtain world settings controller pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; } return pwsc; }