new feature: dynamic flashlights allows usable flashlights

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@6061 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2013-05-03 23:31:28 +00:00
parent 3bc5ff75cc
commit fadd849359
12 changed files with 333 additions and 18 deletions
+2 -1
View File
@@ -21,6 +21,7 @@ extern CHAR16 zTrackingNumber[16];
// Keeps track of the saved game version. Increment the saved game version whenever // Keeps track of the saved game version. Increment the saved game version whenever
// you will invalidate the saved game file // you will invalidate the saved game file
#define DYNAMIC_FLASHLIGHTS 142 // Flugente: had to add variables to LIGHTEFFECT-struct
#define ENLARGED_OPINIONS 141 // Flugente: increased numberof merc opinions to 255, thus need to change savegame reading #define ENLARGED_OPINIONS 141 // Flugente: increased numberof merc opinions to 255, thus need to change savegame reading
#define MODULARIZED_AI 140 // Flugente: new savegame version due to modularized AI #define MODULARIZED_AI 140 // Flugente: new savegame version due to modularized AI
#define MILITIA_EQUIPMENT 139 // Flugente: militia can equip from sector inventory #define MILITIA_EQUIPMENT 139 // Flugente: militia can equip from sector inventory
@@ -60,7 +61,7 @@ extern CHAR16 zTrackingNumber[16];
#define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes #define AP100_SAVEGAME_DATATYPE_CHANGE 105 // Before this, we didn't have the 100AP structure changes
#define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system #define NIV_SAVEGAME_DATATYPE_CHANGE 102 // Before this, we used the old structure system
#define SAVE_GAME_VERSION ENLARGED_OPINIONS #define SAVE_GAME_VERSION DYNAMIC_FLASHLIGHTS
//#define RUSSIANGOLD //#define RUSSIANGOLD
#ifdef __cplusplus #ifdef __cplusplus
+3
View File
@@ -96,6 +96,9 @@ void HandleDoorChangeFromGridNo( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN f
{ {
pDoorStatus->ubFlags |= DOOR_BUSY; pDoorStatus->ubFlags |= DOOR_BUSY;
} }
// Flugente: we have to redo flashlights
pSoldier->HandleFlashLights();
} }
UINT16 GetAnimStateForInteraction( SOLDIERTYPE *pSoldier, BOOLEAN fDoor, UINT16 usAnimState ) UINT16 GetAnimStateForInteraction( SOLDIERTYPE *pSoldier, BOOLEAN fDoor, UINT16 usAnimState )
+21
View File
@@ -111,6 +111,25 @@ void HandleTacticalPanelSwitch( )
} }
} }
// Flugente: handle flashlights
void HandleFlashLights()
{
if ( !fInterfacePanelDirty )
return;
SOLDIERTYPE* pSoldier = NULL;
for (UINT32 uiLoop = 0; uiLoop < guiNumMercSlots; ++uiLoop )
{
pSoldier = MercSlots[ uiLoop ];
if ( pSoldier != NULL && pSoldier->bSoldierFlagMask & SOLDIER_REDOFLASHLIGHT )
{
pSoldier->HandleFlashLights();
}
}
}
void RenderTacticalInterface( ) void RenderTacticalInterface( )
{ {
@@ -143,6 +162,8 @@ void RenderTacticalInterface( )
if( !(guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE ) ) if( !(guiTacticalInterfaceFlags & INTERFACE_SHOPKEEP_INTERFACE ) )
HandleAutoFaces( ); HandleAutoFaces( );
// Flugente: handle flashlights
HandleFlashLights();
} }
+3
View File
@@ -17,6 +17,9 @@ void ResetInterface( );
void RenderTopmostTacticalInterface( ); void RenderTopmostTacticalInterface( );
void RenderTacticalInterface( ); void RenderTacticalInterface( );
// Flugente: handle flashlights
void HandleFlashLights();
void StartViewportOverlays( ); void StartViewportOverlays( );
void EndViewportOverlays( ); void EndViewportOverlays( );
+4
View File
@@ -4089,6 +4089,10 @@ void SMInvClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
*/ */
} }
} }
// Flugente: we have to recheck our flashlights, as we changed items
//gpSMCurrentMerc->bSoldierFlagMask |= SOLDIER_REDOFLASHLIGHT;
gpSMCurrentMerc->HandleFlashLights();
} }
else if (iReason & MSYS_CALLBACK_REASON_RBUTTON_DWN) else if (iReason & MSYS_CALLBACK_REASON_RBUTTON_DWN)
{ {
+3
View File
@@ -1150,6 +1150,9 @@ typedef struct
UINT16 randomitem; UINT16 randomitem;
INT8 randomitemcoolnessmodificator; // alters the allowed maximum coolness a random item can have INT8 randomitemcoolnessmodificator; // alters the allowed maximum coolness a random item can have
// Flugente: range of a flashlight (an item with usFlashLightRange > 0 is deemed a flashlight)
UINT8 usFlashLightRange;
} INVTYPE; } INVTYPE;
+9
View File
@@ -8665,6 +8665,9 @@ void SwapHandItems( SOLDIERTYPE * pSoldier )
SwapObjs( pSoldier, HANDPOS, SECONDHANDPOS, TRUE ); SwapObjs( pSoldier, HANDPOS, SECONDHANDPOS, TRUE );
DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 ); DirtyMercPanelInterface( pSoldier, DIRTYLEVEL2 );
} }
// Flugente: we have to recheck our flashlights
pSoldier->HandleFlashLights();
} }
void SwapOutHandItem( SOLDIERTYPE * pSoldier ) void SwapOutHandItem( SOLDIERTYPE * pSoldier )
@@ -8694,6 +8697,9 @@ void SwapOutHandItem( SOLDIERTYPE * pSoldier )
// otherwise there's no room for the item anywhere! // otherwise there's no room for the item anywhere!
} }
} }
// Flugente: we have to recheck our flashlights
pSoldier->HandleFlashLights();
} }
void WaterDamage( SOLDIERTYPE *pSoldier ) void WaterDamage( SOLDIERTYPE *pSoldier )
@@ -14407,6 +14413,9 @@ BOOLEAN OBJECTTYPE::TransformObject( SOLDIERTYPE * pSoldier, UINT8 ubStatusIndex
} }
} }
// Flugente: we have to recheck our flashlights
pSoldier->HandleFlashLights();
// Signal a successful transformation. // Signal a successful transformation.
return TRUE; return TRUE;
} }
+194 -1
View File
@@ -108,6 +108,7 @@
#include "IMP Skill Trait.h" // added by Flugente #include "IMP Skill Trait.h" // added by Flugente
#include "Food.h" // added by Flugente #include "Food.h" // added by Flugente
#include "Tactical Save.h" // added by Flugente for AddItemsToUnLoadedSector() #include "Tactical Save.h" // added by Flugente for AddItemsToUnLoadedSector()
#include "LightEffects.h" // added by Flugente for CreatePersonalLight()
//forward declarations of common classes to eliminate includes //forward declarations of common classes to eliminate includes
class OBJECTTYPE; class OBJECTTYPE;
@@ -4613,6 +4614,8 @@ void SOLDIERTYPE::SetSoldierGridNo( INT32 sNewGridNo, BOOLEAN fForceRemove )
} }
} }
this->HandleFlashLights();
///HandlePlacingRoofMarker( this, this->sGridNo, TRUE, FALSE ); ///HandlePlacingRoofMarker( this, this->sGridNo, TRUE, FALSE );
this->HandleAnimationProfile( this->usAnimState, FALSE ); this->HandleAnimationProfile( this->usAnimState, FALSE );
@@ -7008,9 +7011,11 @@ void SOLDIERTYPE::ChangeSoldierStance( UINT8 ubDesiredStance )
// Now change to appropriate animation // Now change to appropriate animation
this->EVENT_InitNewSoldierAnim( usNewState, 0 , FALSE ); this->EVENT_InitNewSoldierAnim( usNewState, 0 , FALSE );
}
} }
this->bSoldierFlagMask |= SOLDIER_REDOFLASHLIGHT;
}
void SOLDIERTYPE::EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BOOLEAN fFromMove, UINT16 usAnimState ) void SOLDIERTYPE::EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BOOLEAN fFromMove, UINT16 usAnimState )
{ {
INT32 sNewGridNo; INT32 sNewGridNo;
@@ -7277,6 +7282,9 @@ void SOLDIERTYPE::EVENT_SetSoldierDirection( UINT16 usNewDirection )
// Remove old location data // Remove old location data
this->HandleAnimationProfile( this->usAnimState, TRUE ); this->HandleAnimationProfile( this->usAnimState, TRUE );
// Flugente
BOOLEAN fNew = (this->ubDirection != (INT8)usNewDirection);
this->ubDirection = (INT8)usNewDirection; this->ubDirection = (INT8)usNewDirection;
// Updated extended direction..... // Updated extended direction.....
@@ -7307,6 +7315,9 @@ void SOLDIERTYPE::EVENT_SetSoldierDirection( UINT16 usNewDirection )
// Change values! // Change values!
SetSoldierLocatorOffsets( this ); SetSoldierLocatorOffsets( this );
// Flugente: only update flashlights if we changed our direction
if ( fNew )
this->HandleFlashLights();
} }
@@ -13674,6 +13685,52 @@ BOOLEAN SOLDIERTYPE::SoldierCarriesTwoHandedWeapon( void )
// Flugente: Cool down/decay all items in inventory // Flugente: Cool down/decay all items in inventory
void SOLDIERTYPE::SoldierInventoryCoolDown(void) void SOLDIERTYPE::SoldierInventoryCoolDown(void)
{ {
// if we have any active flashlights (in our hands for simplicity), drain their batteries
// do this check for both hands
UINT16 firstslot = HANDPOS;
UINT16 lastslot = VESTPOCKPOS;
for (UINT16 invpos = firstslot; invpos < lastslot; ++invpos)
{
OBJECTTYPE* pObj = &(this->inv[invpos]);
if ( !pObj || !(pObj->exists()) )
// can't use this, end
continue;
OBJECTTYPE* pBattery = FindAttachedBatteries(pObj);
if ( !pBattery )
continue;
BOOLEAN flashlightfound = FALSE;
if ( Item [ pObj->usItem ].usFlashLightRange )
flashlightfound = TRUE;
if ( !flashlightfound )
{
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
flashlightfound = TRUE;
}
if ( flashlightfound )
{
// 5% chance to lose 1 point
if ( pBattery && Chance(5) )
(*pBattery)[0]->data.objectStatus -= 1;
if ( (*pBattery)[0]->data.objectStatus <= 0 )
{
// destroy batteries
pBattery->RemoveObjectsFromStack(1);
if (pBattery->exists() == false)
this->inv[HANDPOS].RemoveAttachment(pBattery);
}
}
}
// handle flashlight. This is necessary in this location, as we need to do this at least once per turn
this->HandleFlashLights();
if ( !gGameOptions.fWeaponOverheating && !gGameExternalOptions.fDirtSystem && !gGameOptions.fFoodSystem ) if ( !gGameOptions.fWeaponOverheating && !gGameExternalOptions.fDirtSystem && !gGameOptions.fFoodSystem )
return; return;
@@ -15975,6 +16032,9 @@ void SOLDIERTYPE::SwitchWeapons( BOOLEAN fKnife, BOOLEAN fSideArm )
} }
fCharacterInfoPanelDirty = TRUE; fCharacterInfoPanelDirty = TRUE;
fInterfacePanelDirty = DIRTYLEVEL2; fInterfacePanelDirty = DIRTYLEVEL2;
// Flugente: we have to recheck our flashlights
this->HandleFlashLights();
} }
UINT8 tmpuser = 0; UINT8 tmpuser = 0;
@@ -16185,6 +16245,139 @@ void SOLDIERTYPE::AddDrugValues(UINT8 uDrugType, UINT8 usEffect, UINT8 usTravelR
this->bSoldierFlagMask |= SOLDIER_DRUGGED; this->bSoldierFlagMask |= SOLDIER_DRUGGED;
} }
void SOLDIERTYPE::HandleFlashLights()
{
// no more need to redo this check
this->bSoldierFlagMask &= ~SOLDIER_REDOFLASHLIGHT;
// we must be active and in a sector (not travelling) in a valid position
if ( !bActive || !bInSector || TileIsOutOfBounds(this->sGridNo) )
return;
// no flashlight stuff if it isn't night, and we aren't underground
if ( !NightTime() && !gbWorldSectorZ )
return;
// remove existing lights we 'own'
if ( this->bSoldierFlagMask & SOLDIER_LIGHT_OWNER )
{
RemovePersonalLights( this->ubID );
this->bSoldierFlagMask &= ~SOLDIER_LIGHT_OWNER;
}
// not possible to get this bonus on a roof, due to our lighting system
if ( !this->pathing.bLevel )
{
UINT8 flashlightrange = this->GetBestEquippedFlashLightRange();
// the range at which we create additional light sources to the side
UINT8 firstexpand = 8;
UINT8 secondexpand = 12;
// depending on our direction, alter range
if ( this->ubDirection == NORTHEAST || this->ubDirection == NORTHWEST || this->ubDirection == SOUTHEAST || this->ubDirection == SOUTHWEST )
{
flashlightrange = std::sqrt( (FLOAT)flashlightrange*(FLOAT)flashlightrange / 2.0f );
firstexpand = std::sqrt( (FLOAT)firstexpand*(FLOAT)firstexpand / 2.0f );
secondexpand = std::sqrt( (FLOAT)secondexpand*(FLOAT)secondexpand / 2.0f );
}
// if no flashlight is found, this will be 0
if ( flashlightrange )
{
// we determine the height of the next tile in our direction. Because of the way structures are handled, we sometimes have to take the very tile we're occupying right now
INT32 nextGridNoinSight = this->sGridNo;
for(UINT8 i = 0; i < flashlightrange; ++i)
{
nextGridNoinSight = NewGridNo( nextGridNoinSight, DirectionInc( this->ubDirection ) );
if ( SoldierToVirtualSoldierLineOfSightTest( this, nextGridNoinSight, this->pathing.bLevel, gAnimControl[ this->usAnimState ].ubEndHeight, FALSE ) )
CreatePersonalLight( nextGridNoinSight, this->ubID );
// after a certain range, add new lights to the side to simulate a light cone
if ( i > firstexpand )
{
INT8 sidedir1 = (this->ubDirection + 2) % NUM_WORLD_DIRECTIONS;
INT8 sidedir2 = (this->ubDirection - 2) % NUM_WORLD_DIRECTIONS;
INT32 sideGridNo1 = NewGridNo( nextGridNoinSight, DirectionInc( sidedir1 ) );
sideGridNo1 = NewGridNo( sideGridNo1, DirectionInc( sidedir1 ) );
if ( SoldierToVirtualSoldierLineOfSightTest( this, sideGridNo1, this->pathing.bLevel, gAnimControl[ this->usAnimState ].ubEndHeight, FALSE, NO_DISTANCE_LIMIT ) )
CreatePersonalLight( sideGridNo1, this->ubID );
if ( i > secondexpand )
{
sideGridNo1 = NewGridNo( sideGridNo1, DirectionInc( sidedir1 ) );
if ( SoldierToVirtualSoldierLineOfSightTest( this, sideGridNo1, this->pathing.bLevel, gAnimControl[ this->usAnimState ].ubEndHeight, FALSE, NO_DISTANCE_LIMIT ) )
CreatePersonalLight( sideGridNo1, this->ubID );
}
INT32 sideGridNo2 = NewGridNo( nextGridNoinSight, DirectionInc( sidedir2 ) );
sideGridNo2 = NewGridNo( sideGridNo2, DirectionInc( sidedir2 ) );
if ( SoldierToVirtualSoldierLineOfSightTest( this, sideGridNo2, this->pathing.bLevel, gAnimControl[ this->usAnimState ].ubEndHeight, FALSE, NO_DISTANCE_LIMIT ) )
CreatePersonalLight( sideGridNo2, this->ubID );
if ( i > secondexpand )
{
sideGridNo2 = NewGridNo( sideGridNo2, DirectionInc( sidedir2 ) );
if ( SoldierToVirtualSoldierLineOfSightTest( this, sideGridNo2, this->pathing.bLevel, gAnimControl[ this->usAnimState ].ubEndHeight, FALSE, NO_DISTANCE_LIMIT ) )
CreatePersonalLight( sideGridNo2, this->ubID );
}
}
}
// take note: we own a light source
this->bSoldierFlagMask |= SOLDIER_LIGHT_OWNER;
}
}
// refresh sight for everybody
AllTeamsLookForAll( TRUE );
SetRenderFlags(RENDER_FLAG_FULL);
}
UINT8 SOLDIERTYPE::GetBestEquippedFlashLightRange()
{
UINT8 bestrange = 0;
// do this check for both hands
UINT16 firstslot = HANDPOS;
UINT16 lastslot = VESTPOCKPOS;
for (UINT16 invpos = firstslot; invpos < lastslot; ++invpos)
{
OBJECTTYPE* pObj = &(this->inv[invpos]);
if ( !pObj || !(pObj->exists()) )
// can't use this, end
continue;
// due to our attachment system, flashlights on guns do not require the batteries to be attached to the flashlight itself - anywhere will do
if ( !FindAttachedBatteries(pObj) )
continue;
if ( Item [ pObj->usItem ].usFlashLightRange )
{
bestrange = max(bestrange, Item [ pObj->usItem ].usFlashLightRange);
}
attachmentList::iterator iterend = (*pObj)[0]->attachments.end();
for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != iterend; ++iter)
{
if(iter->exists() && Item [ iter->usItem ].usFlashLightRange )
bestrange = max(bestrange, Item [ iter->usItem ].usFlashLightRange);
}
}
return( bestrange );
}
INT32 CheckBleeding( SOLDIERTYPE *pSoldier ) INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
{ {
INT8 bBandaged; //,savedOurTurn; INT8 bBandaged; //,savedOurTurn;
+6 -3
View File
@@ -367,10 +367,10 @@ enum
#define SOLDIER_POW_PRISON 0x00001000 //4096 // this guy is a prisoner of war in a prison sector. SOLDIER_POW refers to people we capture, this refers to people we hold captive #define SOLDIER_POW_PRISON 0x00001000 //4096 // this guy is a prisoner of war in a prison sector. SOLDIER_POW refers to people we capture, this refers to people we hold captive
#define SOLDIER_EQUIPMENT_DROPPED 0x00002000 //8192 // under certain circumstances, militia can be ordered to drop their gear twice. Thus we set a marker to avoid that. #define SOLDIER_EQUIPMENT_DROPPED 0x00002000 //8192 // under certain circumstances, militia can be ordered to drop their gear twice. Thus we set a marker to avoid that.
#define SOLDIER_ACCESSTEAMMEMBER 0x00004000 //16384 // this merc is accessing another team member'S inventory (via abusing the stealing mechanic) #define SOLDIER_ACCESSTEAMMEMBER 0x00004000 //16384 // this merc is accessing another team member'S inventory (via abusing the stealing mechanic)
/*#define ENEMY_NET_4_LVL_4 0x00008000 //32768 #define SOLDIER_REDOFLASHLIGHT 0x00008000 //32768 // this flag signifies that we somehow interacted with the items in our hands. Thus we have to possible redo lighting from flashlights
#define PLAYER_NET_1_LVL_1 0x00010000 //65536 #define SOLDIER_LIGHT_OWNER 0x00010000 //65536 // we 'own' at least one light source (via flashlights)
#define PLAYER_NET_2_LVL_1 0x00020000 //131072 /*#define PLAYER_NET_2_LVL_1 0x00020000 //131072
#define PLAYER_NET_3_LVL_1 0x00040000 //262144 #define PLAYER_NET_3_LVL_1 0x00040000 //262144
#define PLAYER_NET_4_LVL_1 0x00080000 //524288 #define PLAYER_NET_4_LVL_1 0x00080000 //524288
@@ -1560,6 +1560,9 @@ public:
INT8 GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubTargetProfile ); INT8 GetTraitCTHModifier( UINT16 usItem, INT16 ubAimTime, UINT8 ubTargetProfile );
void AddDrugValues(UINT8 uDrugType, UINT8 usEffect, UINT8 usTravelRate, UINT8 usSideEffect ); void AddDrugValues(UINT8 uDrugType, UINT8 usEffect, UINT8 usTravelRate, UINT8 usSideEffect );
void HandleFlashLights();
UINT8 GetBestEquippedFlashLightRange();
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
}; // SOLDIERTYPE; }; // SOLDIERTYPE;
+68 -9
View File
@@ -26,6 +26,7 @@
#endif #endif
#include "SaveLoadGame.h" #include "SaveLoadGame.h"
#include "GameVersion.h" // added by Flugente
//forward declarations of common classes to eliminate includes //forward declarations of common classes to eliminate includes
@@ -33,7 +34,7 @@ class OBJECTTYPE;
class SOLDIERTYPE; class SOLDIERTYPE;
#define NUM_LIGHT_EFFECT_SLOTS 25 #define NUM_LIGHT_EFFECT_SLOTS 500 // 25 // Flugente: raised to 500 - lets see what happens
// GLOBAL FOR LIGHT LISTING // GLOBAL FOR LIGHT LISTING
@@ -102,8 +103,8 @@ void UpdateLightingSprite( LIGHTEFFECT *pLight )
LightSpritePosition( pLight->iLight, (INT16)( CenterX( pLight->sGridNo ) / CELL_X_SIZE ), (INT16)( CenterY( pLight->sGridNo ) / CELL_Y_SIZE ) ); LightSpritePosition( pLight->iLight, (INT16)( CenterX( pLight->sGridNo ) / CELL_X_SIZE ), (INT16)( CenterY( pLight->sGridNo ) / CELL_Y_SIZE ) );
} }
// Flugente: create a pure light, worry about updating sight in other functions
INT32 NewLightEffect( INT32 sGridNo, UINT8 ubDuration, UINT8 ubStartRadius ) INT32 NewLightEffectInternal( INT32 sGridNo, UINT8 ubDuration, UINT8 ubStartRadius )
{ {
LIGHTEFFECT *pLight; LIGHTEFFECT *pLight;
INT32 iLightIndex; INT32 iLightIndex;
@@ -127,13 +128,27 @@ INT32 NewLightEffect( INT32 sGridNo, UINT8 ubDuration, UINT8 ubStartRadius )
UpdateLightingSprite( pLight ); UpdateLightingSprite( pLight );
return iLightIndex;
}
INT32 NewLightEffect( INT32 sGridNo, UINT8 ubDuration, UINT8 ubStartRadius )
{
INT32 iLightIndex = NewLightEffectInternal( sGridNo, ubDuration, ubStartRadius );
// Handle sight here.... // Handle sight here....
AllTeamsLookForAll( FALSE ); AllTeamsLookForAll( FALSE );
//Play the breaklight sound //Play the breaklight sound
// PlayJA2Sample( BREAK_LIGHT_IGNITING, RATE_11025, SoundVolume( LOWVOLUME, sGridNo ), 1, SoundDir( sGridNo ) ); // PlayJA2Sample( BREAK_LIGHT_IGNITING, RATE_11025, SoundVolume( LOWVOLUME, sGridNo ), 1, SoundDir( sGridNo ) );
// MAdd: for some reason this crashes the game! // MAdd: for some reason this crashes the game!
return( pLight->iLight );
if ( iLightIndex > -1 )
{
LIGHTEFFECT *pLight = &gLightEffectData[ iLightIndex ];
return( pLight->iLight );
}
return -1;
} }
@@ -468,12 +483,25 @@ BOOLEAN LoadLightEffectsFromMapTempFile( INT16 sMapX, INT16 sMapY, INT8 bMapZ )
//loop through and load the list //loop through and load the list
for( uiCnt=0; uiCnt<guiNumLightEffects;uiCnt++) for( uiCnt=0; uiCnt<guiNumLightEffects;uiCnt++)
{ {
//Load the Light effect Data if(guiCurrentSaveGameVersion >= DYNAMIC_FLASHLIGHTS)
FileRead( hFile, &gLightEffectData[ uiCnt ], sizeof( LIGHTEFFECT ), &uiNumBytesRead );
if( uiNumBytesRead != sizeof( LIGHTEFFECT ) )
{ {
FileClose( hFile ); //Load the Light effect Data
return( FALSE ); FileRead( hFile, &gLightEffectData[ uiCnt ], sizeof( LIGHTEFFECT ), &uiNumBytesRead );
if( uiNumBytesRead != sizeof( LIGHTEFFECT ) )
{
return( FALSE );
}
}
else
{
UINT16 bla = sizeof( LIGHTEFFECT );
//Load the Light effect Data
FileRead( hFile, &gLightEffectData[ uiCnt ], LIGHTEFFECT_OLDSIZE, &uiNumBytesRead );
if( uiNumBytesRead != LIGHTEFFECT_OLDSIZE )
{
return( FALSE );
}
} }
} }
@@ -497,3 +525,34 @@ void ResetLightEffects()
memset( gLightEffectData, 0, sizeof( LIGHTEFFECT ) * NUM_LIGHT_EFFECT_SLOTS ); memset( gLightEffectData, 0, sizeof( LIGHTEFFECT ) * NUM_LIGHT_EFFECT_SLOTS );
guiNumLightEffects = 0; guiNumLightEffects = 0;
} }
// Flugente: create and destroy light sources tied to a person
void CreatePersonalLight( INT32 sGridNo, UINT8 ubID )
{
INT32 iLightIndex = NewLightEffectInternal( sGridNo, 0, 1 );
if ( iLightIndex > -1 )
{
gLightEffectData[ iLightIndex ].ubOwner = ubID;
gLightEffectData[ iLightIndex ].flags |= LIGHTEFFECT_FLASHLIGHT;
}
}
void RemovePersonalLights( UINT8 ubID )
{
LIGHTEFFECT *pLight;
// Set to unallocated....
for ( UINT32 cnt = 0; cnt < guiNumLightEffects; ++cnt )
{
pLight = &gLightEffectData[ cnt ];
if ( pLight->iLight != (-1) && pLight->flags & LIGHTEFFECT_FLASHLIGHT && pLight->ubOwner == ubID && pLight->fAllocated )
{
pLight->fAllocated = FALSE;
pLight->flags &= ~LIGHTEFFECT_FLASHLIGHT;
LightSpriteDestroy( pLight->iLight );
}
}
}
+10
View File
@@ -23,8 +23,14 @@ typedef struct
INT32 iLight; INT32 iLight;
UINT32 uiTimeOfLastUpdate; UINT32 uiTimeOfLastUpdate;
// Flugente: added variables necessary for dynamic (flash-)lighting
INT32 flags;
UINT8 ubOwner;
} LIGHTEFFECT; } LIGHTEFFECT;
#define LIGHTEFFECT_OLDSIZE 20 // Flugente: the old size of LIGHTEFFECT (before Gameversion DYNAMIC_FLASHLIGHTS)
#define LIGHTEFFECT_FLASHLIGHT 0x00000001
// Decays all light effects... // Decays all light effects...
@@ -48,4 +54,8 @@ void ResetLightEffects();
BOOLEAN IsLightEffectAtTile( INT32 sGridNo ); BOOLEAN IsLightEffectAtTile( INT32 sGridNo );
// Flugente: create and destroy light sources tied to a person
void CreatePersonalLight( INT32 sGridNo, UINT8 ubID );
void RemovePersonalLights( UINT8 ubID );
#endif #endif
+10 -4
View File
@@ -272,7 +272,8 @@ itemStartElementHandle(void *userData, const XML_Char *name, const XML_Char **at
strcmp(name, "usActionItemFlag") == 0 || strcmp(name, "usActionItemFlag") == 0 ||
strcmp(name, "clothestype") == 0 || strcmp(name, "clothestype") == 0 ||
strcmp(name, "randomitem") == 0 || strcmp(name, "randomitem") == 0 ||
strcmp(name, "randomitemcoolnessmodificator") == 0 )) strcmp(name, "randomitemcoolnessmodificator") == 0 ||
strcmp(name, "FlashLightRange") == 0 ))
{ {
pData->curElement = ELEMENT_PROPERTY; pData->curElement = ELEMENT_PROPERTY;
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("itemStartElementHandle: going into element, name = %s",name) ); //DebugMsg(TOPIC_JA2, DBG_LEVEL_3, String("itemStartElementHandle: going into element, name = %s",name) );
@@ -1406,8 +1407,12 @@ itemEndElementHandle(void *userData, const XML_Char *name)
// no nonsense, only values between -20 and + 20 // no nonsense, only values between -20 and + 20
pData->curItem.randomitemcoolnessmodificator = min(20, max(-20, pData->curItem.randomitemcoolnessmodificator) ); pData->curItem.randomitemcoolnessmodificator = min(20, max(-20, pData->curItem.randomitemcoolnessmodificator) );
} }
else if(strcmp(name, "FlashLightRange") == 0)
{
pData->curElement = ELEMENT;
pData->curItem.usFlashLightRange = (UINT8) atol(pData->szCharData);
}
pData->maxReadDepth--; pData->maxReadDepth--;
} }
@@ -2044,7 +2049,8 @@ BOOLEAN WriteItemStats()
FilePrintf(hFile,"\t\t<clothestype>%d</clothestype>\r\n", Item[cnt].clothestype ); FilePrintf(hFile,"\t\t<clothestype>%d</clothestype>\r\n", Item[cnt].clothestype );
FilePrintf(hFile,"\t\t<randomitem>%d</randomitem>\r\n", Item[cnt].randomitem ); FilePrintf(hFile,"\t\t<randomitem>%d</randomitem>\r\n", Item[cnt].randomitem );
FilePrintf(hFile,"\t\t<randomitemcoolnessmodificator>%d</randomitemcoolnessmodificator>\r\n", Item[cnt].randomitemcoolnessmodificator ); FilePrintf(hFile,"\t\t<randomitemcoolnessmodificator>%d</randomitemcoolnessmodificator>\r\n", Item[cnt].randomitemcoolnessmodificator );
FilePrintf(hFile,"\t\t<FlashLightRange>%d</FlashLightRange>\r\n", Item[cnt].usFlashLightRange );
FilePrintf(hFile,"\t</ITEM>\r\n"); FilePrintf(hFile,"\t</ITEM>\r\n");
} }
FilePrintf(hFile,"</ITEMLIST>\r\n"); FilePrintf(hFile,"</ITEMLIST>\r\n");