Original Source for 1.13 Mod High Resolution version from 12/06/05

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@21 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
lalien
2006-04-19 11:32:51 +00:00
commit e54aeb96aa
790 changed files with 741287 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
#ifndef ACTION_ITEMS_H
#define ACTION_ITEMS_H
typedef enum
{
ACTION_ITEM_OPEN_DOOR = 1,
ACTION_ITEM_CLOSE_DOOR,
ACTION_ITEM_BLOW_UP,
ACTION_ITEM_SMALL_PIT,
ACTION_ITEM_LARGE_PIT,
ACTION_ITEM_TOGGLE_DOOR,
ACTION_ITEM_TOGGLE_ACTION1,
ACTION_ITEM_TOGGLE_ACTION2,
ACTION_ITEM_TOGGLE_ACTION3,
ACTION_ITEM_TOGGLE_ACTION4,
ACTION_ITEM_ENTER_BROTHEL,
ACTION_ITEM_EXIT_BROTHEL,
ACTION_ITEM_KINGPIN_ALARM,
ACTION_ITEM_SEX,
ACTION_ITEM_REVEAL_ROOM,
ACTION_ITEM_LOCAL_ALARM,
ACTION_ITEM_GLOBAL_ALARM,
ACTION_ITEM_KLAXON,
ACTION_ITEM_UNLOCK_DOOR,
ACTION_ITEM_TOGGLE_LOCK,
ACTION_ITEM_UNTRAP_DOOR,
ACTION_ITEM_TOGGLE_PRESSURE_ITEMS,
ACTION_ITEM_MUSEUM_ALARM,
ACTION_ITEM_BLOODCAT_ALARM
} ItemActionType;
#endif
File diff suppressed because it is too large Load Diff
+65
View File
@@ -0,0 +1,65 @@
#ifndef AIR_RAID_H
#define AIR_RAID_H
#include "soldier control.h"
#define AIR_RAID_BEGINNING_GAME 0x00000001
#define AIR_RAID_CAN_RANDOMIZE_TEASE_DIVES 0x00000002
#define AIR_RAID_BOMBS_ONLY 0x00000004
typedef struct
{
INT16 sSectorX;
INT16 sSectorY;
INT16 sSectorZ;
INT8 bIntensity;
UINT32 uiFlags;
UINT8 ubNumMinsFromCurrentTime;
UINT8 ubFiller[8];
} AIR_RAID_DEFINITION;
extern BOOLEAN gfInAirRaid;
// what ari raid mode are we in?
extern UINT8 gubAirRaidMode;
enum AIR_RAID_STATES
{
AIR_RAID_TRYING_TO_START,
AIR_RAID_START,
AIR_RAID_LOOK_FOR_DIVE,
AIR_RAID_BEGIN_DIVE,
AIR_RAID_DIVING,
AIR_RAID_END_DIVE,
AIR_RAID_BEGIN_BOMBING,
AIR_RAID_BOMBING,
AIR_RAID_END_BOMBING,
AIR_RAID_START_END,
AIR_RAID_END
} ;
void ScheduleAirRaid( AIR_RAID_DEFINITION *pAirRaidDef );
void HandleAirRaid( );
BOOLEAN BeginAirRaid( );
BOOLEAN InAirRaid( );
BOOLEAN HandleAirRaidEndTurn( UINT8 ubTeam );
//Save the air raid info to the saved game
BOOLEAN SaveAirRaidInfoToSaveGameFile( HWFILE hFile );
//load the air raid info from the saved game
BOOLEAN LoadAirRaidInfoFromSaveGameFile( HWFILE hFile );
void EndAirRaid( );
#endif
+167
View File
@@ -0,0 +1,167 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include <stdio.h>
#include <string.h>
#include "types.h"
#include "wcheck.h"
#include "stdlib.h"
#include "debug.h"
#include "Animation Cache.h"
#include "Animation Data.h"
#include "Animation Control.h"
#include "sys globals.h"
#include "Debug Control.h"
#endif
#define EMPTY_CACHE_ENTRY 65000
UINT32 guiCacheSize = MIN_CACHE_SIZE;
void DetermineOptimumAnimationCacheSize( )
{
// If we have lots-a memory, adjust accordingly!
guiCacheSize = MIN_CACHE_SIZE;
}
BOOLEAN InitAnimationCache( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache )
{
UINT32 cnt;
// Allocate entries
AnimDebugMsg( String( "*** Initializing anim cache surface for soldier %d", usSoldierID ) );
pAnimCache->usCachedSurfaces = (UINT16 *) MemAlloc( sizeof( UINT16 ) * guiCacheSize );
CHECKF( pAnimCache->usCachedSurfaces!= NULL );
AnimDebugMsg( String( "*** Initializing anim cache hit counter for soldier %d", usSoldierID ) );
pAnimCache->sCacheHits = (INT16 *) MemAlloc( sizeof( UINT16) * guiCacheSize );
CHECKF( pAnimCache->sCacheHits!= NULL );
// Zero entries
for ( cnt = 0; cnt < guiCacheSize; cnt++ )
{
pAnimCache->usCachedSurfaces[ cnt ] = EMPTY_CACHE_ENTRY;
pAnimCache->sCacheHits[ cnt ] = 0;
}
pAnimCache->ubCacheSize = 0;
// Zero surface databse history for this soldeir
ClearAnimationSurfacesUsageHistory( usSoldierID );
return( TRUE );
}
void DeleteAnimationCache( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache )
{
// Allocate entries
if ( pAnimCache->usCachedSurfaces!= NULL )
{
AnimDebugMsg( String( "*** Removing Anim Cache surface for soldier %d", usSoldierID ) );
MemFree( pAnimCache->usCachedSurfaces );
}
if ( pAnimCache->sCacheHits != NULL )
{
AnimDebugMsg( String( "*** Removing Anim Cache hit counter for soldier %d", usSoldierID ) );
MemFree( pAnimCache->sCacheHits );
}
}
BOOLEAN GetCachedAnimationSurface( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache, UINT16 usSurfaceIndex, UINT16 usCurrentAnimation )
{
UINT8 cnt;
UINT8 ubLowestIndex = 0;
INT16 sMostHits = (INT16)32000;
UINT16 usCurrentAnimSurface;
// Check to see if surface exists already
for ( cnt = 0; cnt < pAnimCache->ubCacheSize; cnt++ )
{
if ( pAnimCache->usCachedSurfaces[ cnt ] == usSurfaceIndex )
{
// Found surface, return
AnimDebugMsg( String( "Anim Cache: Hit %d ( Soldier %d )", usSurfaceIndex, usSoldierID ) );
pAnimCache->sCacheHits[cnt]++;
return( TRUE );
}
}
// Check if max size has been reached
if ( pAnimCache->ubCacheSize == guiCacheSize )
{
AnimDebugMsg( String( "Anim Cache: Determining Bump Candidate ( Soldier %d )", usSoldierID ) );
// Determine exisiting surface used by merc
usCurrentAnimSurface = DetermineSoldierAnimationSurface( MercPtrs[ usSoldierID ], usCurrentAnimation );
// If the surface we are going to bump is our existing animation, reject it as a candidate
// If we get here, we need to remove an animation, pick the best one
// Loop through and pick one with lowest cache hits
for ( cnt = 0; cnt < pAnimCache->ubCacheSize; cnt++ )
{
AnimDebugMsg( String( "Anim Cache: Slot %d Hits %d ( Soldier %d )", cnt, pAnimCache->sCacheHits[ cnt ], usSoldierID ) );
if ( pAnimCache->usCachedSurfaces[ cnt ] == usCurrentAnimSurface )
{
AnimDebugMsg( String( "Anim Cache: REJECTING Slot %d EXISTING ANIM SURFACE ( Soldier %d )", cnt, usSoldierID ) );
}
else
{
if ( pAnimCache->sCacheHits[ cnt ] < sMostHits )
{
sMostHits = pAnimCache->sCacheHits[ cnt ];
ubLowestIndex = cnt;
}
}
}
// Bump off lowest index
AnimDebugMsg( String( "Anim Cache: Bumping %d ( Soldier %d )", ubLowestIndex, usSoldierID ) );
UnLoadAnimationSurface( usSoldierID, pAnimCache->usCachedSurfaces[ ubLowestIndex ] );
// Decrement
pAnimCache->sCacheHits[ ubLowestIndex ] = 0;
pAnimCache->usCachedSurfaces[ ubLowestIndex ] = EMPTY_CACHE_ENTRY;
pAnimCache->ubCacheSize--;
}
// If here, Insert at an empty slot
// Find an empty slot
for ( cnt = 0; cnt < guiCacheSize; cnt++ )
{
if ( pAnimCache->usCachedSurfaces[ cnt ] == EMPTY_CACHE_ENTRY )
{
AnimDebugMsg( String( "Anim Cache: Loading Surface %d ( Soldier %d )", usSurfaceIndex, usSoldierID ) );
// Insert here
CHECKF( LoadAnimationSurface( usSoldierID, usSurfaceIndex, usCurrentAnimation ) != FALSE );
pAnimCache->sCacheHits[ cnt ] = 0;
pAnimCache->usCachedSurfaces[ cnt ] = usSurfaceIndex;
pAnimCache->ubCacheSize++;
break;
}
}
return( TRUE );
}
void UnLoadCachedAnimationSurfaces( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache )
{
UINT8 cnt;
// Check to see if surface exists already
for ( cnt = 0; cnt < pAnimCache->ubCacheSize; cnt++ )
{
if ( pAnimCache->usCachedSurfaces[ cnt ] != EMPTY_CACHE_ENTRY )
{
UnLoadAnimationSurface( usSoldierID, pAnimCache->usCachedSurfaces[ cnt ] );
}
}
}
+28
View File
@@ -0,0 +1,28 @@
#ifndef __ANIMATION_CACHE_H
#define __ANIMATION_CACHE_H
#include "types.h"
#define MAX_CACHE_SIZE 20
#define MIN_CACHE_SIZE 2
typedef struct
{
UINT16 *usCachedSurfaces;
INT16 *sCacheHits;
UINT8 ubCacheSize;
} AnimationSurfaceCacheType;
extern UINT32 guiCacheSize;
BOOLEAN GetCachedAnimationSurface( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache, UINT16 usSurfaceIndex, UINT16 usCurrentAnimation );
BOOLEAN InitAnimationCache( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache );
void DeleteAnimationCache( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache );
void DetermineOptimumAnimationCacheSize( );
void UnLoadCachedAnimationSurfaces( UINT16 usSoldierID, AnimationSurfaceCacheType *pAnimCache );
#endif
File diff suppressed because it is too large Load Diff
+571
View File
@@ -0,0 +1,571 @@
#ifndef __ANIMATION_CONTROL_H
#define __ANIMATION_CONTROL_H
// Header file for merc animation control
#include "Soldier Control.h"
#include "Animation Data.h"
// Defines
// #######################################################
#define MAX_ANIMATIONS 320
#define MAX_FRAMES_PER_ANIM 100
#define MAX_RANDOM_ANIMS_PER_BODYTYPE 7
#define RANDOM_ANIM_NOTHINGINHAND 0
#define RANDOM_ANIM_RIFLEINHAND 1
#define RANDOM_ANIM_IRRELEVENTINHAND 2
#define RANDOM_ANIM_SOUND 250
#define RANDOM_ANIM_CASUAL 0x01
#define RANDOM_ANIM_SECONDBIGMERC 0x02
#define RANDOM_ANIM_FIRSTBIGMERC 0x04
#define RANDOM_ANIM_INJURED 0x08
#define RANDOM_ANIM_DRUNK 0x10
#define INJURED_CHANGE_THREASHOLD 30
#define USESTATS 0
#define FAST_TURN_ANIM_SPEED 30
#define INVALID_ANIMATION_SURFACE 32000
// FLAG DEFINES
#define ANIM_IGNORE_AUTOSTANCE 0x00000001
#define ANIM_OK_CHARGE_AP_FOR_TURN 0x00000002
#define ANIM_STATIONARY 0x00000004
#define ANIM_MOVING 0x00000008
#define ANIM_TURNING 0x00000010
#define ANIM_FASTTURN 0x00000020
#define ANIM_FIREREADY 0x00000040
#define ANIM_NONINTERRUPT 0x00000080
#define ANIM_HITFINISH 0x00000100
#define ANIM_HITSTART 0x00000200
#define ANIM_HITWHENDOWN 0x00000400
#define ANIM_NOSHOW_MARKER 0x00000800
#define ANIM_NOMOVE_MARKER 0x00001000
#define ANIM_NORESTART 0x00002000
#define ANIM_HITSTOP 0x00004000
#define ANIM_SPECIALMOVE 0x00008000
#define ANIM_MERCIDLE 0x00010000
#define ANIM_STANCECHANGEANIM 0x00020000
#define ANIM_LOWER_WEAPON 0x00040000
#define ANIM_RAISE_WEAPON 0x00080000
#define ANIM_NOCHANGE_WEAPON 0x00100000
#define ANIM_NOCHANGE_PENDINGCOUNT 0x00200000
#define ANIM_NO_EFFORT 0x00400000
#define ANIM_MIN_EFFORT 0x00800000
#define ANIM_LIGHT_EFFORT 0x01000000
#define ANIM_MODERATE_EFFORT 0x02000000
#define ANIM_RT_NONINTERRUPT 0x04000000
#define ANIM_VARIABLE_EFFORT 0x08000000
#define ANIM_UPDATEMOVEMENTMODE 0x10000000
#define ANIM_FIRE 0x20000000
#define ANIM_BREATH 0x40000000
#define ANIM_IGNOREHITFINISH 0x80000000
//ANIMATION HEIGHT VALUES
#define ANIM_STAND 6
#define ANIM_CROUCH 3
#define ANIM_PRONE 1
#define INVALID_ANIMATION 0xFFF0
#define FOUND_INVALID_ANIMATION 0xFFF1
#define MAX_ANIM_STR_SIZE 35 //30 1 byte overflow! (jonathanl)
// Enumerations
// #######################################################
// STRUCTURES
// ###################################################################
typedef struct
{
CHAR8 zAnimStr[ MAX_ANIM_STR_SIZE ];
INT16 sAP;
INT16 sSpeed;
FLOAT dMovementChange;
UINT32 uiFlags;
UINT8 ubHeight;
UINT8 ubEndHeight;
INT8 bProfile;
} ANIMCONTROLTYPE;
typedef struct
{
INT16 sSpeed;
FLOAT dMovementChange;
} ANI_SPEED_DEF;
typedef struct
{
UINT8 ubHandRestriction;
INT16 sAnimID;
UINT8 ubStartRoll;
UINT8 ubEndRoll;
UINT8 ubFlags;
UINT8 ubAnimHeight;
INT8 zSoundFile[ 30 ];
} RANDOM_ANI_DEF;
// Enumeration of animation states
enum AnimationStates
{
WALKING = 0,
STANDING,
KNEEL_DOWN,
CROUCHING,
KNEEL_UP,
SWATTING,
RUNNING,
PRONE_DOWN,
CRAWLING,
PRONE_UP,
PRONE,
READY_RIFLE_STAND,
AIM_RIFLE_STAND,
SHOOT_RIFLE_STAND,
END_RIFLE_STAND,
START_SWAT,
END_SWAT,
FLYBACK_HIT,
READY_RIFLE_PRONE,
AIM_RIFLE_PRONE,
SHOOT_RIFLE_PRONE,
END_RIFLE_PRONE,
FALLBACK_DEATHTWICH,
GENERIC_HIT_STAND,
FLYBACK_HIT_BLOOD_STAND,
FLYBACK_HIT_DEATH,
READY_RIFLE_CROUCH,
AIM_RIFLE_CROUCH,
SHOOT_RIFLE_CROUCH,
END_RIFLE_CROUCH,
FALLBACK_HIT_STAND,
ROLLOVER,
CLIMBUPROOF,
FALLOFF,
GETUP_FROM_ROLLOVER,
CLIMBDOWNROOF,
FALLFORWARD_ROOF,
GENERIC_HIT_DEATHTWITCHNB,
GENERIC_HIT_DEATHTWITCHB,
FALLBACK_HIT_DEATHTWITCHNB,
FALLBACK_HIT_DEATHTWITCHB,
GENERIC_HIT_DEATH,
FALLBACK_HIT_DEATH,
GENERIC_HIT_CROUCH,
STANDING_BURST,
STANDING_BURST_HIT,
FALLFORWARD_FROMHIT_STAND,
FALLFORWARD_FROMHIT_CROUCH,
ENDFALLFORWARD_FROMHIT_CROUCH,
GENERIC_HIT_PRONE,
PRONE_HIT_DEATH,
PRONE_LAY_FROMHIT,
PRONE_HIT_DEATHTWITCHNB,
PRONE_HIT_DEATHTWITCHB,
ADULTMONSTER_BREATHING,
ADULTMONSTER_WALKING,
ADULTMONSTER_ATTACKING,
FLYBACK_HITDEATH_STOP,
FALLFORWARD_HITDEATH_STOP,
FALLBACK_HITDEATH_STOP,
PRONE_HITDEATH_STOP,
FLYBACKHIT_STOP,
FALLBACKHIT_STOP,
FALLOFF_STOP,
FALLOFF_FORWARD_STOP,
STAND_FALLFORWARD_STOP,
PRONE_LAYFROMHIT_STOP,
HOPFENCE,
ADULTMONSTER_HIT,
ADULTMONSTER_DYING,
ADULTMONSTER_DYING_STOP,
PUNCH_BREATH,
PUNCH,
NOTHING_STAND,
JFK_HITDEATH,
JFK_HITDEATH_STOP,
JFK_HITDEATH_TWITCHB,
FIRE_STAND_BURST_SPREAD,
FALLOFF_DEATH,
FALLOFF_DEATH_STOP,
FALLOFF_TWITCHB,
FALLOFF_TWITCHNB,
FALLOFF_FORWARD_DEATH,
FALLOFF_FORWARD_DEATH_STOP,
FALLOFF_FORWARD_TWITCHB,
FALLOFF_FORWARD_TWITCHNB,
OPEN_DOOR,
OPEN_STRUCT,
PICKUP_ITEM,
DROP_ITEM,
SLICE,
STAB,
CROUCH_STAB,
START_AID,
GIVING_AID,
END_AID,
DODGE_ONE,
FATCIV_ASS_SCRATCH,
READY_DUAL_STAND,
AIM_DUAL_STAND,
SHOOT_DUAL_STAND,
END_DUAL_STAND,
RAISE_RIFLE,
LOWER_RIFLE,
BODYEXPLODING,
THROW_ITEM,
LOB_ITEM,
QUEEN_MONSTER_BREATHING,
CROUCHED_BURST,
PRONE_BURST,
NOTUSEDANIM1,
BIGBUY_FLEX,
BIGBUY_STRECH,
BIGBUY_SHOEDUST,
BIGBUY_HEADTURN,
MINIGIRL_STOCKING,
GIVE_ITEM,
CLIMB_CLIFF,
COW_EATING,
COW_HIT,
COW_DYING,
COW_DYING_STOP,
WATER_HIT,
WATER_DIE,
WATER_DIE_STOP,
CROW_WALK,
CROW_TAKEOFF,
CROW_LAND,
CROW_FLY,
CROW_EAT,
HELIDROP,
FEM_CLEAN,
FEM_KICKSN,
FEM_LOOK,
FEM_WIPE,
REG_SQUISH,
REG_PULL,
REG_SPIT,
HATKID_YOYO,
KID_ARMPIT,
MONSTER_CLOSE_ATTACK,
MONSTER_SPIT_ATTACK,
MONSTER_BEGIN_EATTING_FLESH,
MONSTER_EATTING_FLESH,
MONSTER_END_EATTING_FLESH,
BLOODCAT_RUN,
BLOODCAT_STARTREADY,
BLOODCAT_READY,
BLOODCAT_ENDREADY,
BLOODCAT_HIT,
BLOODCAT_DYING,
BLOODCAT_DYING_STOP,
BLOODCAT_SWIPE,
NINJA_GOTOBREATH,
NINJA_BREATH,
NINJA_LOWKICK,
NINJA_PUNCH,
NINJA_SPINKICK,
END_OPEN_DOOR,
END_OPEN_LOCKED_DOOR,
KICK_DOOR,
CLOSE_DOOR,
RIFLE_STAND_HIT,
DEEP_WATER_TRED,
DEEP_WATER_SWIM,
DEEP_WATER_HIT,
DEEP_WATER_DIE,
DEEP_WATER_DIE_STOPPING,
DEEP_WATER_DIE_STOP,
LOW_TO_DEEP_WATER,
DEEP_TO_LOW_WATER,
GOTO_SLEEP,
SLEEPING,
WKAEUP_FROM_SLEEP,
FIRE_LOW_STAND,
FIRE_BURST_LOW_STAND,
LARVAE_BREATH,
LARVAE_HIT,
LARVAE_DIE,
LARVAE_DIE_STOP,
LARVAE_WALK,
INFANT_HIT,
INFANT_DIE,
INFANT_DIE_STOP,
INFANT_ATTACK,
INFANT_BEGIN_EATTING_FLESH,
INFANT_EATTING_FLESH,
INFANT_END_EATTING_FLESH,
MONSTER_UP,
MONSTER_JUMP,
STANDING_SHOOT_UNJAM,
CROUCH_SHOOT_UNJAM,
PRONE_SHOOT_UNJAM,
STANDING_SHOOT_DWEL_UNJAM,
STANDING_SHOOT_LOW_UNJAM,
READY_DUAL_CROUCH,
AIM_DUAL_CROUCH,
SHOOT_DUAL_CROUCH,
END_DUAL_CROUCH,
CROUCH_SHOOT_DWEL_UNJAM,
ADJACENT_GET_ITEM,
CUTTING_FENCE,
CRIPPLE_BEG,
CRIPPLE_HIT,
CRIPPLE_DIE,
CRIPPLE_DIE_STOP,
CRIPPLE_DIE_FLYBACK,
CRIPPLE_DIE_FLYBACK_STOP,
CRIPPLE_KICKOUT,
FROM_INJURED_TRANSITION,
THROW_KNIFE,
KNIFE_BREATH,
KNIFE_GOTOBREATH,
KNIFE_ENDBREATH,
ROBOTNW_HIT,
ROBOTNW_DIE,
ROBOTNW_DIE_STOP,
CATCH_STANDING,
CATCH_CROUCHED,
PLANT_BOMB,
USE_REMOTE,
START_COWER,
COWERING,
END_COWER,
STEAL_ITEM,
SHOOT_ROCKET,
CIV_DIE2,
SHOOT_MORTAR,
CROW_DIE,
SIDE_STEP,
WALK_BACKWARDS,
BEGIN_OPENSTRUCT,
END_OPENSTRUCT,
END_OPENSTRUCT_LOCKED,
PUNCH_LOW,
PISTOL_SHOOT_LOW,
DECAPITATE,
BLOODCAT_BITE_ANIM,
BIGMERC_IDLE_NECK,
BIGMERC_CROUCH_TRANS_INTO,
BIGMERC_CROUCH_TRANS_OUTOF,
GOTO_PATIENT,
BEING_PATIENT,
GOTO_DOCTOR,
BEING_DOCTOR,
END_DOCTOR,
GOTO_REPAIRMAN,
BEING_REPAIRMAN,
END_REPAIRMAN,
FALL_INTO_PIT,
ROBOT_WALK,
ROBOT_SHOOT,
QUEEN_HIT,
QUEEN_DIE,
QUEEN_DIE_STOP,
QUEEN_INTO_READY,
QUEEN_READY,
QUEEN_END_READY,
QUEEN_CALL,
QUEEN_SPIT,
QUEEN_SWIPE,
RELOAD_ROBOT,
END_CATCH,
END_CROUCH_CATCH,
AI_RADIO,
AI_CR_RADIO,
TANK_SHOOT,
TANK_BURST,
QUEEN_SLAP,
SLAP_HIT,
TAKE_BLOOD_FROM_CORPSE,
VEHICLE_DIE,
QUEEN_FRUSTRATED_SLAP,
CHARIOTS_OF_FIRE,
AI_PULL_SWITCH,
MONSTER_MELT,
MERC_HURT_IDLE_ANIM,
END_HURT_WALKING,
PASS_OBJECT,
DROP_ADJACENT_OBJECT,
READY_DUAL_PRONE,
AIM_DUAL_PRONE,
SHOOT_DUAL_PRONE,
END_DUAL_PRONE,
PRONE_SHOOT_DWEL_UNJAM,
PICK_LOCK,
OPEN_DOOR_CROUCHED,
BEGIN_OPENSTRUCT_CROUCHED,
CLOSE_DOOR_CROUCHED,
OPEN_STRUCT_CROUCHED,
END_OPEN_DOOR_CROUCHED,
END_OPENSTRUCT_CROUCHED,
END_OPEN_LOCKED_DOOR_CROUCHED,
END_OPENSTRUCT_LOCKED_CROUCHED,
DRUNK_IDLE,
CROWBAR_ATTACK,
CIV_COWER_HIT,
BLOODCAT_WALK_BACKWARDS,
MONSTER_WALK_BACKWARDS,
KID_SKIPPING,
ROBOT_BURST_SHOOT,
ATTACH_CAN_TO_STRING,
SWAT_BACKWARDS,
JUMP_OVER_BLOCKING_PERSON,
REFUEL_VEHICLE,
ROBOT_CAMERA_NOT_MOVING,
CRIPPLE_OPEN_DOOR,
CRIPPLE_CLOSE_DOOR,
CRIPPLE_END_OPEN_DOOR,
CRIPPLE_END_OPEN_LOCKED_DOOR,
LOCKPICK_CROUCHED,
NUMANIMATIONSTATES
};
extern UINT16 gusAnimInst[ MAX_ANIMATIONS ][ MAX_FRAMES_PER_ANIM ];
extern ANIMCONTROLTYPE gAnimControl[ NUMANIMATIONSTATES ];
extern ANI_SPEED_DEF gubAnimWalkSpeeds[ TOTALBODYTYPES ];
extern ANI_SPEED_DEF gubAnimRunSpeeds[ TOTALBODYTYPES ];
extern ANI_SPEED_DEF gubAnimSwatSpeeds[ TOTALBODYTYPES ];
extern ANI_SPEED_DEF gubAnimCrawlSpeeds[ TOTALBODYTYPES ];
extern UINT8 gubMaxActionPoints[ TOTALBODYTYPES ];
// OK, this array contains definitions for random animations based on bodytype, total # allowed, and what is in their hand....
extern RANDOM_ANI_DEF gRandomAnimDefs[ TOTALBODYTYPES ][ MAX_RANDOM_ANIMS_PER_BODYTYPE ];
// Corpse Defines
extern UINT16 gubAnimSurfaceCorpseID[ TOTALBODYTYPES ][ NUMANIMATIONSTATES ];
//FUNCTIONS
BOOLEAN LoadAnimationStateInstructions( );
void InitAnimationSurfacesPerBodytype( );
BOOLEAN IsAnimationValidForBodyType( SOLDIERTYPE *pSoldier, UINT16 usNewState );
BOOLEAN SubstituteBodyTypeAnimation( SOLDIERTYPE *pSoldier, UINT16 usTestState, UINT16 *pusSubState );
INT8 GetBodyTypePaletteSubstitutionCode( SOLDIERTYPE *pSoldier, UINT8 ubBodyType, CHAR8 *zColFilename );
BOOLEAN SetSoldierAnimationSurface( SOLDIERTYPE *pSoldier, UINT16 usAnimState );
UINT16 DetermineSoldierAnimationSurface( SOLDIERTYPE *pSoldier, UINT16 usAnimState );
UINT16 LoadSoldierAnimationSurface( SOLDIERTYPE *pSoldier, UINT16 usAnimState );
// This function could be wrapped in a debug marco, since it only returns pSoldier->ubAnimSurface but
// Also does some debug checking
UINT16 GetSoldierAnimationSurface( SOLDIERTYPE *pSoldier, UINT16 usAnimState );
#endif
File diff suppressed because it is too large Load Diff
+571
View File
@@ -0,0 +1,571 @@
#ifndef ANIMATION_DATA_H_
#define ANIMATION_DATA_H_
#include "vobject.h"
#include "Soldier Control.h"
#include "Overhead.h"
#include "Structure Internals.h"
// DEFINES FOR ANIMATION PROFILES
#define TILE_FLAG_FEET 0x0001
#define TILE_FLAG_MID 0x0002
#define TILE_FLAG_HEAD 0x0004
#define TILE_FLAG_CANMOVE 0x0008
#define TILE_FLAG_NORTH_HALF 0x0010
#define TILE_FLAG_SOUTH_HALF 0x0020
#define TILE_FLAG_WEST_HALF 0x0040
#define TILE_FLAG_EAST_HALF 0x0080
#define TILE_FLAG_TOP_HALF 0x0100
#define TILE_FLAG_BOTTOM_HALF 0x0200
#define ANIM_DATA_FLAG_NOFRAMES 0x01
// ENUMERATIONS
// BODY TYPES
// RGM = Regular Male
// (RG) = Body desc ( Regular - RG, Short Stocky ( SS ), etc
// (M) = Sex, Male, female
#define IS_MERC_BODY_TYPE( p ) ( ( p->ubBodyType <= REGFEMALE ) ? ( TRUE ) : ( FALSE ) )
#define IS_CIV_BODY_TYPE( p ) ( (p->ubBodyType >= FATCIV) && (p->ubBodyType <= CRIPPLECIV) )
#define NUMSOLDIERBODYTYPES 4
enum SoldierBodyTypes
{
REGMALE = 0,
BIGMALE,
STOCKYMALE,
REGFEMALE,
ADULTFEMALEMONSTER,
AM_MONSTER,
YAF_MONSTER,
YAM_MONSTER,
LARVAE_MONSTER,
INFANT_MONSTER,
QUEENMONSTER,
FATCIV,
MANCIV,
MINICIV,
DRESSCIV,
HATKIDCIV,
KIDCIV,
CRIPPLECIV,
COW,
CROW,
BLOODCAT,
ROBOTNOWEAPON,
HUMVEE,
TANK_NW,
TANK_NE,
ELDORADO,
ICECREAMTRUCK,
JEEP,
TOTALBODYTYPES
} ;
// Enumerations
// This enumeration defines the graphic image file per animation
// RGM = Regular Male
// (RG) = Body desc ( Regular - RG, Short Stocky ( SS ), etc
// (M) = Sex, Male, female
typedef enum
{
RGMBASICWALKING = 0,
RGMSTANDING,
RGMCROUCHING,
RGMSNEAKING,
RGMRUNNING,
RGMPRONE,
RGMSTANDAIM,
RGMHITHARD,
RGMHITSTAND,
RGMHITHARDBLOOD,
RGMCROUCHAIM,
RGMHITFALLBACK,
RGMROLLOVER,
RGMCLIMBROOF,
RGMFALL,
RGMFALLF,
RGMHITCROUCH,
RGMHITPRONE,
RGMHOPFENCE,
RGMPUNCH,
RGMNOTHING_STD,
RGMNOTHING_WALK,
RGMNOTHING_RUN,
RGMNOTHING_SWAT,
RGMNOTHING_CROUCH,
RGMHANDGUN_S_SHOT,
RGMHANDGUN_C_SHOT,
RGMHANDGUN_PRONE,
RGMDIE_JFK,
RGMOPEN,
RGMPICKUP,
RGMSTAB,
RGMSLICE,
RGMCSTAB,
RGMMEDIC,
RGMDODGE,
RGMSTANDDWALAIM,
RGMRAISE,
RGMTHROW,
RGMLOB,
RGMKICKDOOR,
RGMRHIT,
RGM_SQUISH,
RGM_LOOK,
RGM_PULL,
RGM_SPIT,
RGMWATER_R_WALK,
RGMWATER_R_STD,
RGMWATER_N_WALK,
RGMWATER_N_STD,
RGMWATER_DIE,
RGMWATER_N_AIM,
RGMWATER_R_AIM,
RGMWATER_DBLSHT,
RGMWATER_TRANS,
RGMDEEPWATER_TRED,
RGMDEEPWATER_SWIM,
RGMDEEPWATER_DIE,
RGMMCLIMB,
RGMHELIDROP,
RGMLOWKICK,
RGMNPUNCH,
RGMSPINKICK,
RGMSLEEP,
RGMSHOOT_LOW,
RGMCDBLSHOT,
RGMHURTSTANDINGN,
RGMHURTSTANDINGR,
RGMHURTWALKINGN,
RGMHURTWALKINGR,
RGMHURTTRANS,
RGMTHROWKNIFE,
RGMBREATHKNIFE,
RGMPISTOLBREATH,
RGMCOWER,
RGMROCKET,
RGMMORTAR,
RGMSIDESTEP,
RGMDBLBREATH,
RGMPUNCHLOW,
RGMPISTOLSHOOTLOW,
RGMWATERTHROW,
RGMRADIO,
RGMCRRADIO,
RGMBURN,
RGMDWPRONE,
RGMDRUNK,
RGMPISTOLDRUNK,
RGMCROWBAR,
RGMJUMPOVER,
BGMWALKING,
BGMSTANDING,
BGMCROUCHING,
BGMSNEAKING,
BGMRUNNING,
BGMPRONE,
BGMSTANDAIM,
BGMHITHARD,
BGMHITSTAND,
BGMHITHARDBLOOD,
BGMCROUCHAIM,
BGMHITFALLBACK,
BGMROLLOVER,
BGMCLIMBROOF,
BGMFALL,
BGMFALLF,
BGMHITCROUCH,
BGMHITPRONE,
BGMHOPFENCE,
BGMPUNCH,
BGMNOTHING_STD,
BGMNOTHING_WALK,
BGMNOTHING_RUN,
BGMNOTHING_SWAT,
BGMNOTHING_CROUCH,
BGMHANDGUN_S_SHOT,
BGMHANDGUN_C_SHOT,
BGMHANDGUN_PRONE,
BGMDIE_JFK,
BGMOPEN,
BGMPICKUP,
BGMSTAB,
BGMSLICE,
BGMCSTAB,
BGMMEDIC,
BGMDODGE,
BGMSTANDDWALAIM,
BGMRAISE,
BGMTHROW,
BGMLOB,
BGMKICKDOOR,
BGMRHIT,
BGMSTANDAIM2,
BGMFLEX,
BGMSTRECH,
BGMSHOEDUST,
BGMHEADTURN,
BGMWATER_R_WALK,
BGMWATER_R_STD,
BGMWATER_N_WALK,
BGMWATER_N_STD,
BGMWATER_DIE,
BGMWATER_N_AIM,
BGMWATER_R_AIM,
BGMWATER_DBLSHT,
BGMWATER_TRANS,
BGMDEEPWATER_TRED,
BGMDEEPWATER_SWIM,
BGMDEEPWATER_DIE,
BGMHELIDROP,
BGMSLEEP,
BGMSHOOT_LOW,
BGMTHREATENSTAND,
BGMCDBLSHOT,
BGMHURTSTANDINGN,
BGMHURTSTANDINGR,
BGMHURTWALKINGN,
BGMHURTWALKINGR,
BGMHURTTRANS,
BGMTHROWKNIFE,
BGMBREATHKNIFE,
BGMPISTOLBREATH,
BGMCOWER,
BGMRAISE2,
BGMROCKET,
BGMMORTAR,
BGMSIDESTEP,
BGMDBLBREATH,
BGMPUNCHLOW,
BGMPISTOLSHOOTLOW,
BGMWATERTHROW,
BGMWALK2,
BGMRUN2,
BGMIDLENECK,
BGMCROUCHTRANS,
BGMRADIO,
BGMCRRADIO,
BGMDWPRONE,
BGMDRUNK,
BGMPISTOLDRUNK,
BGMCROWBAR,
BGMJUMPOVER,
RGFWALKING,
RGFSTANDING,
RGFCROUCHING,
RGFSNEAKING,
RGFRUNNING,
RGFPRONE,
RGFSTANDAIM,
RGFHITHARD,
RGFHITSTAND,
RGFHITHARDBLOOD,
RGFCROUCHAIM,
RGFHITFALLBACK,
RGFROLLOVER,
RGFCLIMBROOF,
RGFFALL,
RGFFALLF,
RGFHITCROUCH,
RGFHITPRONE,
RGFHOPFENCE,
RGFPUNCH,
RGFNOTHING_STD,
RGFNOTHING_WALK,
RGFNOTHING_RUN,
RGFNOTHING_SWAT,
RGFNOTHING_CROUCH,
RGFHANDGUN_S_SHOT,
RGFHANDGUN_C_SHOT,
RGFHANDGUN_PRONE,
RGFDIE_JFK,
RGFOPEN,
RGFPICKUP,
RGFSTAB,
RGFSLICE,
RGFCSTAB,
RGFMEDIC,
RGFDODGE,
RGFSTANDDWALAIM,
RGFRAISE,
RGFTHROW,
RGFLOB,
RGFKICKDOOR,
RGFRHIT,
RGFCLEAN,
RGFKICKSN,
RGFALOOK,
RGFWIPE,
RGFWATER_R_WALK,
RGFWATER_R_STD,
RGFWATER_N_WALK,
RGFWATER_N_STD,
RGFWATER_DIE,
RGFWATER_N_AIM,
RGFWATER_R_AIM,
RGFWATER_DBLSHT,
RGFWATER_TRANS,
RGFDEEPWATER_TRED,
RGFDEEPWATER_SWIM,
RGFDEEPWATER_DIE,
RGFHELIDROP,
RGFSLEEP,
RGFSHOOT_LOW,
RGFCDBLSHOT,
RGFHURTSTANDINGN,
RGFHURTSTANDINGR,
RGFHURTWALKINGN,
RGFHURTWALKINGR,
RGFHURTTRANS,
RGFTHROWKNIFE,
RGFBREATHKNIFE,
RGFPISTOLBREATH,
RGFCOWER,
RGFROCKET,
RGFMORTAR,
RGFSIDESTEP,
RGFDBLBREATH,
RGFPUNCHLOW,
RGFPISTOLSHOOTLOW,
RGFWATERTHROW,
RGFRADIO,
RGFCRRADIO,
RGFSLAP,
RGFDWPRONE,
RGFDRUNK,
RGFPISTOLDRUNK,
RGFCROWBAR,
RGFJUMPOVER,
AFMONSTERSTANDING,
AFMONSTERWALKING,
AFMONSTERATTACK,
AFMONSTERCLOSEATTACK,
AFMONSTERSPITATTACK,
AFMONSTEREATING,
AFMONSTERDIE,
AFMUP,
AFMJUMP,
AFMMELT,
LVBREATH,
LVDIE,
LVWALK,
IBREATH,
IWALK,
IDIE,
IEAT,
IATTACK,
QUEENMONSTERSTANDING,
QUEENMONSTERREADY,
QUEENMONSTERSPIT_SW,
QUEENMONSTERSPIT_E,
QUEENMONSTERSPIT_NE,
QUEENMONSTERSPIT_S,
QUEENMONSTERSPIT_SE,
QUEENMONSTERDEATH,
QUEENMONSTERSWIPE,
FATMANSTANDING,
FATMANWALKING,
FATMANRUNNING,
FATMANDIE,
FATMANASS,
FATMANACT,
FATMANCOWER,
FATMANDIE2,
FATMANCOWERHIT,
MANCIVSTANDING,
MANCIVWALKING,
MANCIVRUNNING,
MANCIVDIE,
MANCIVACT,
MANCIVCOWER,
MANCIVDIE2,
MANCIVSMACKED,
MANCIVPUNCH,
MANCIVCOWERHIT,
MINICIVSTANDING,
MINICIVWALKING,
MINICIVRUNNING,
MINICIVDIE,
MINISTOCKING,
MINIACT,
MINICOWER,
MINIDIE2,
MINICOWERHIT,
DRESSCIVSTANDING,
DRESSCIVWALKING,
DRESSCIVRUNNING,
DRESSCIVDIE,
DRESSCIVACT,
DRESSCIVCOWER,
DRESSCIVDIE2,
DRESSCIVCOWERHIT,
HATKIDCIVSTANDING,
HATKIDCIVWALKING,
HATKIDCIVRUNNING,
HATKIDCIVDIE,
HATKIDCIVJFK,
HATKIDCIVYOYO,
HATKIDCIVACT,
HATKIDCIVCOWER,
HATKIDCIVDIE2,
HATKIDCIVCOWERHIT,
HATKIDCIVSKIP,
KIDCIVSTANDING,
KIDCIVWALKING,
KIDCIVRUNNING,
KIDCIVDIE,
KIDCIVJFK,
KIDCIVARMPIT,
KIDCIVACT,
KIDCIVCOWER,
KIDCIVDIE2,
KIDCIVCOWERHIT,
KIDCIVSKIP,
CRIPCIVSTANDING,
CRIPCIVWALKING,
CRIPCIVRUNNING,
CRIPCIVBEG,
CRIPCIVDIE,
CRIPCIVDIE2,
CRIPCIVKICK,
COWSTANDING,
COWWALKING,
COWDIE,
COWEAT,
CROWWALKING,
CROWFLYING,
CROWEATING,
CROWDYING,
CATBREATH,
CATWALK,
CATRUN,
CATREADY,
CATHIT,
CATDIE,
CATSWIPE,
CATBITE,
ROBOTNWBREATH,
ROBOTNWWALK,
ROBOTNWHIT,
ROBOTNWDIE,
ROBOTNWSHOOT,
HUMVEE_BASIC,
HUMVEE_DIE,
TANKNW_READY,
TANKNW_SHOOT,
TANKNW_DIE,
TANKNE_READY,
TANKNE_SHOOT,
TANKNE_DIE,
ELDORADO_BASIC,
ELDORADO_DIE,
ICECREAMTRUCK_BASIC,
ICECREAMTRUCK_DIE,
JEEP_BASIC,
JEEP_DIE,
BODYEXPLODE,
NUMANIMATIONSURFACETYPES
} AnimationSurfaceTypes;
// Enumerations for struct data
typedef enum
{
S_STRUCT,
C_STRUCT,
P_STRUCT,
F_STRUCT,
FB_STRUCT,
DEFAULT_STRUCT,
NUM_STRUCT_IDS,
NO_STRUCT = 120,
};
// Struct for animation 'surface' information
typedef struct
{
UINT16 ubName;
CHAR8 Filename[ 50 ];
CHAR8 bStructDataType;
UINT8 ubFlags;
UINT32 uiNumDirections;
UINT32 uiNumFramesPerDir;
HVOBJECT hVideoObject;
void *Unused;
INT8 bUsageCount;
INT8 bProfile;
} AnimationSurfaceType;
typedef struct
{
CHAR8 Filename[ 50 ];
STRUCTURE_FILE_REF * pStructureFileRef;
} AnimationStructureType;
extern AnimationSurfaceType gAnimSurfaceDatabase[ NUMANIMATIONSURFACETYPES ];
extern AnimationStructureType gAnimStructureDatabase[ TOTALBODYTYPES ][ NUM_STRUCT_IDS ];
// Functions
BOOLEAN InitAnimationSystem( );
BOOLEAN DeInitAnimationSystem( );
BOOLEAN LoadAnimationSurface( UINT16 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState );
BOOLEAN UnLoadAnimationSurface( UINT16 usSoldierID, UINT16 usSurfaceIndex );
void ClearAnimationSurfacesUsageHistory( UINT16 usSoldierID );
void DeleteAnimationProfiles( );
BOOLEAN LoadAnimationProfiles( );
STRUCTURE_FILE_REF *GetAnimationStructureRef( UINT16 usSoldierID, UINT16 usSurfaceIndex, UINT16 usAnimState );
STRUCTURE_FILE_REF *GetDefaultStructureRef( UINT16 usSoldierID );
// Profile data
extern ANIM_PROF *gpAnimProfiles;
extern UINT8 gubNumAnimProfiles;
void ZeroAnimSurfaceCounts( );
#endif
File diff suppressed because it is too large Load Diff
+299
View File
@@ -0,0 +1,299 @@
#ifndef _ARMS_DEALERS_INIT__H_
#define _ARMS_DEALERS_INIT__H_
#include "Store Inventory.h"
//enums for the various arms dealers
enum
{
ARMS_DEALER_TONY,
ARMS_DEALER_FRANZ,
ARMS_DEALER_KEITH,
ARMS_DEALER_JAKE,
ARMS_DEALER_GABBY,
ARMS_DEALER_DEVIN,
ARMS_DEALER_HOWARD,
ARMS_DEALER_SAM,
ARMS_DEALER_FRANK,
ARMS_DEALER_BAR_BRO_1,
ARMS_DEALER_BAR_BRO_2,
ARMS_DEALER_BAR_BRO_3,
ARMS_DEALER_BAR_BRO_4,
ARMS_DEALER_MICKY,
ARMS_DEALER_ARNIE,
ARMS_DEALER_FREDO,
ARMS_DEALER_PERKO,
// added only in GameVersion 54
ARMS_DEALER_ELGIN,
// added only in GameVersion 55
ARMS_DEALER_MANNY,
NUM_ARMS_DEALERS,
};
//the enums for the different kinds of arms dealers
enum
{
ARMS_DEALER_BUYS_SELLS,
ARMS_DEALER_SELLS_ONLY,
ARMS_DEALER_BUYS_ONLY,
ARMS_DEALER_REPAIRS,
};
//The following defines indicate what items can be sold by the arms dealer
#define ARMS_DEALER_HANDGUNCLASS 0x00000001
#define ARMS_DEALER_SMGCLASS 0x00000002
#define ARMS_DEALER_RIFLECLASS 0x00000004
#define ARMS_DEALER_MGCLASS 0x00000008
#define ARMS_DEALER_SHOTGUNCLASS 0x00000010
#define ARMS_DEALER_KNIFECLASS 0x00000020
#define ARMS_DEALER_BLADE 0x00000040
#define ARMS_DEALER_LAUNCHER 0x00000080
#define ARMS_DEALER_ARMOUR 0x00000100
#define ARMS_DEALER_MEDKIT 0x00000200
#define ARMS_DEALER_MISC 0x00000400
#define ARMS_DEALER_AMMO 0x00000800
#define ARMS_DEALER_GRENADE 0x00001000
#define ARMS_DEALER_BOMB 0x00002000
#define ARMS_DEALER_EXPLOSV 0x00004000
#define ARMS_DEALER_KIT 0x00008000
#define ARMS_DEALER_FACE 0x00010000
//#define ARMS_DEALER_THROWN 0x00020000
//#define ARMS_DEALER_KEY 0x00040000
//#define ARMS_DEALER_VIDEO_CAMERA 0x00020000
#define ARMS_DEALER_DETONATORS 0x00040000
#define ARMS_DEALER_ATTACHMENTS 0x00080000
#define ARMS_DEALER_ALCOHOL 0x00100000
#define ARMS_DEALER_ELECTRONICS 0x00200000
#define ARMS_DEALER_HARDWARE 0x00400000 | ARMS_DEALER_KIT
#define ARMS_DEALER_MEDICAL 0x00800000 | ARMS_DEALER_MEDKIT
//#define ARMS_DEALER_EMPTY_JAR 0x01000000
#define ARMS_DEALER_CREATURE_PARTS 0x02000000
#define ARMS_DEALER_ROCKET_RIFLE 0x04000000
#define ARMS_DEALER_ONLY_USED_ITEMS 0x08000000
#define ARMS_DEALER_GIVES_CHANGE 0x10000000 //The arms dealer will give the required change when doing a transaction
#define ARMS_DEALER_ACCEPTS_GIFTS 0x20000000 //The arms dealer is the kind of person who will accept gifts
#define ARMS_DEALER_SOME_USED_ITEMS 0x40000000 //The arms dealer can have used items in his inventory
#define ARMS_DEALER_HAS_NO_INVENTORY 0x80000000 //The arms dealer does not carry any inventory
#define ARMS_DEALER_ALL_GUNS ARMS_DEALER_HANDGUNCLASS | ARMS_DEALER_SMGCLASS | ARMS_DEALER_RIFLECLASS | ARMS_DEALER_MGCLASS | ARMS_DEALER_SHOTGUNCLASS
#define ARMS_DEALER_BIG_GUNS ARMS_DEALER_SMGCLASS | ARMS_DEALER_RIFLECLASS | ARMS_DEALER_MGCLASS | ARMS_DEALER_SHOTGUNCLASS
#define ARMS_DEALER_ALL_WEAPONS ARMS_DEALER_ALL_GUNS | ARMS_DEALER_BLADE | ARMS_DEALER_LAUNCHER | ARMS_DEALER_KNIFECLASS
//
// Specific Dealer Flags
// NOTE: Each dealer has 8 flags, but different dealers can and SHOULD share the same flag #s!
//
// Alex Fredo
#define ARMS_DEALER_FLAG__FREDO_HAS_SAID_ROCKET_RIFLE_QUOTE 0x00000001 // Alex Fredo has already repaired the Rocket Rifle
// Franz Hinkle
#define ARMS_DEALER_FLAG__FRANZ_HAS_SOLD_VIDEO_CAMERA_TO_PLAYER 0x00000001 // Franz Hinkle has sold the video camera to the player
// THIS STRUCTURE HAS UNCHANGING INFO THAT DOESN'T GET SAVED/RESTORED/RESET
typedef struct
{
union
{
struct
{
FLOAT dBuyModifier; // The price modifier used when this dealer is BUYING something.
FLOAT dSellModifier; // The price modifier used when this dealer is SELLING something.
};
struct
{
FLOAT dRepairSpeed; // Modifier to the speed at which a repairman repairs things
FLOAT dRepairCost; // Modifier to the price a repairman charges for repairs
};
};
UINT8 ubShopKeeperID; // Merc Id for the dealer
UINT8 ubTypeOfArmsDealer; // Whether he buys/sells, sells, buys, or repairs
INT32 iInitialCash; // How much cash dealer starts with (we now reset to this amount once / day)
UINT32 uiFlags; // various flags which control the dealer's operations
} ARMS_DEALER_INFO;
// THIS STRUCTURE GETS SAVED/RESTORED/RESET
typedef struct
{
UINT32 uiArmsDealersCash; // How much money the arms dealer currently has
UINT8 ubSpecificDealerFlags; // Misc state flags for specific dealers
BOOLEAN fOutOfBusiness; // Set when a dealer has been killed, etc.
BOOLEAN fRepairDelayBeenUsed; // Set when a repairman has missed his repair time estimate & given his excuse for it
BOOLEAN fUnusedKnowsPlayer; // Set if the shopkeeper has met with the player before [UNUSED]
UINT32 uiTimePlayerLastInSKI; // game time (in total world minutes) when player last talked to this dealer in SKI
UINT8 ubPadding[ 8 ];
} ARMS_DEALER_STATUS;
typedef struct
{
UINT16 usAttachment[MAX_ATTACHMENTS]; // item index of any attachments on the item
INT8 bItemCondition; // if 0, no item is stored
// from 1 to 100 indicates an item with that status
// -1 to -100 means the item is in for repairs, flip sign for the actual status
UINT8 ubImprintID; // imprint ID for imprinted items (during repair!)
INT8 bAttachmentStatus[MAX_ATTACHMENTS]; // status of any attachments on the item
UINT8 ubPadding[2]; // filler
} SPECIAL_ITEM_INFO;
typedef struct
{
// Individual "special" items are stored here as needed, *one* per slot
// An item is special if it is used (status < 100), has been imprinted, or has a permanent attachment
SPECIAL_ITEM_INFO Info;
UINT32 uiRepairDoneTime; // If the item is in for repairs, this holds the time when it will be repaired (in min)
BOOLEAN fActive; // TRUE means an item is stored here (empty elements may not always be freed immediately)
UINT8 ubOwnerProfileId; // stores which merc previously owned an item being repaired
UINT8 ubPadding[6]; // filler
} DEALER_SPECIAL_ITEM;
typedef struct
{
// Non-special items are all the identical and are totaled inside ubPerfectItems.
// Items being repaired are also stored here, with a negative condition.
// NOTE: special item elements may remain allocated long after item has been removed, to reduce memory fragmentation!!!
UINT8 ubTotalItems; // sum of all the items (all perfect ones + all special ones)
UINT8 ubPerfectItems; // non-special (perfect) items held by dealer
UINT8 ubStrayAmmo; // partially-depleted ammo mags are stored here as #bullets, and can be converted to full packs
UINT8 ubElementsAlloced; // number of DEALER_SPECIAL_ITEM array elements alloced for the special item array
DEALER_SPECIAL_ITEM *SpecialItem; // dynamic array of special items with this same item index
UINT32 uiOrderArrivalTime; // Day the items ordered will arrive on. It's UINT32 in case we change this to minutes.
UINT8 ubQtyOnOrder; // The number of items currently on order
BOOLEAN fPreviouslyEligible; // whether or not dealer has been eligible to sell this item in days prior to today
UINT8 ubPadding[2]; // filler
} DEALER_ITEM_HEADER;
extern ARMS_DEALER_INFO ArmsDealerInfo[ NUM_ARMS_DEALERS ];
extern ARMS_DEALER_STATUS gArmsDealerStatus[ NUM_ARMS_DEALERS ];
extern DEALER_ITEM_HEADER gArmsDealersInventory[ NUM_ARMS_DEALERS ][ MAXITEMS ];
void InitAllArmsDealers();
void ShutDownArmsDealers();
UINT32 GetArmsDealerItemTypeFromItemNumber( UINT16 usItem );
//Count every single item the dealer has in stock
//UINT32 CountTotalItemsInArmsDealersInventory( UINT8 ubArmsDealer );
//Count only the # of "distinct" item types (for shopkeeper purposes)
UINT32 CountDistinctItemsInArmsDealersInventory( UINT8 ubArmsDealer );
UINT8 CountActiveSpecialItemsInArmsDealersInventory( UINT8 ubArmsDealer, UINT16 usItemIndex );
UINT16 CountTotalItemsRepairDealerHasInForRepairs( UINT8 ubArmsDealer );
UINT8 CountSpecificItemsRepairDealerHasInForRepairs( UINT8 ubArmsDealer, UINT16 usItemIndex );
void AddObjectToArmsDealerInventory( UINT8 ubArmsDealer, OBJECTTYPE *pObject );
void RemoveItemFromArmsDealerInventory( UINT8 ubArmsDealer, UINT16 usItemIndex, SPECIAL_ITEM_INFO *pSpclItemInfo, UINT8 ubHowMany );
void RemoveSpecialItemFromArmsDealerInventoryAtElement( UINT8 ubArmsDealer, UINT16 usItemIndex, UINT8 ubElement );
BOOLEAN IsMercADealer( UINT8 ubMercID );
INT8 GetArmsDealerIDFromMercID( UINT8 ubMercID );
BOOLEAN SaveArmsDealerInventoryToSaveGameFile( HWFILE hFile );
BOOLEAN LoadArmsDealerInventoryFromSavedGameFile( HWFILE hFile, BOOLEAN fIncludesElgin, BOOLEAN fIncludesManny );
void DailyUpdateOfArmsDealersInventory();
UINT8 GetTypeOfArmsDealer( UINT8 ubDealerID );
BOOLEAN DoesDealerDoRepairs( UINT8 ubArmsDealer );
BOOLEAN RepairmanIsFixingItemsButNoneAreDoneYet( UINT8 ubProfileID );
UINT32 GetTimeToFixItemBeingRepaired( UINT8 ubArmsDealer, UINT16 usItemIndex, UINT8 ubElement );
BOOLEAN CanDealerTransactItem( UINT8 ubArmsDealer, UINT16 usItemIndex, BOOLEAN fPurchaseFromPlayer );
BOOLEAN CanDealerRepairItem( UINT8 ubArmsDealer, UINT16 usItemIndex );
BOOLEAN AddDeadArmsDealerItemsToWorld( UINT8 ubMercID );
void MakeObjectOutOfDealerItems( UINT16 usItemIndex, SPECIAL_ITEM_INFO *pSpclItemInfo, OBJECTTYPE *pObject, UINT8 ubHowMany );
void GiveObjectToArmsDealerForRepair( UINT8 ubArmsDealer, OBJECTTYPE *pObject, UINT8 ubOwnerProfileId );
void GiveItemToArmsDealerforRepair( UINT8 ubArmsDealer, UINT16 usItemIndex, SPECIAL_ITEM_INFO *pSpclItemInfo, UINT8 ubOwnerProfileId );
UINT32 WhenWillRepairmanBeAllDoneRepairing( UINT8 ubArmsDealer );
UINT32 CalculateSpecialItemRepairTime( UINT8 ubArmsDealer, UINT16 usItemIndex, SPECIAL_ITEM_INFO *pSpclItemInfo );
UINT32 CalculateObjectItemRepairTime( UINT8 ubArmsDealer, OBJECTTYPE *pItemObject );
UINT32 CalculateSimpleItemRepairTime( UINT8 ubArmsDealer, UINT16 usItemIndex, INT8 bItemCondition );
UINT32 CalculateSpecialItemRepairCost( UINT8 ubArmsDealer, UINT16 usItemIndex, SPECIAL_ITEM_INFO *pSpclItemInfo );
UINT32 CalculateObjectItemRepairCost( UINT8 ubArmsDealer, OBJECTTYPE *pItemObject );
UINT32 CalculateSimpleItemRepairCost( UINT8 ubArmsDealer, UINT16 usItemIndex, INT8 bItemCondition );
void SetSpecialItemInfoToDefaults( SPECIAL_ITEM_INFO *pSpclItemInfo );
void SetSpecialItemInfoFromObject( SPECIAL_ITEM_INFO *pSpclItemInfo, OBJECTTYPE *pObject );
UINT16 CalcValueOfItemToDealer( UINT8 ubArmsDealer, UINT16 usItemIndex, BOOLEAN fDealerSelling );
BOOLEAN DealerItemIsSafeToStack( UINT16 usItemIndex );
UINT32 CalculateOvernightRepairDelay( UINT8 ubArmsDealer, UINT32 uiTimeWhenFreeToStartIt, UINT32 uiMinutesToFix );
UINT32 CalculateMinutesClosedBetween( UINT8 ubArmsDealer, UINT32 uiStartTime, UINT32 uiEndTime );
#endif
File diff suppressed because it is too large Load Diff
+76
View File
@@ -0,0 +1,76 @@
#ifndef _ARMS_DEALER_INV_INIT__H_
#define _ARMS_DEALER_INV_INIT__H_
#define LAST_DEALER_ITEM 0//-1
#define NO_DEALER_ITEM 0
// item suitability categories for dealer inventory initialization, virtual customer sales, and re-ordering
#define ITEM_SUITABILITY_NONE 0
#define ITEM_SUITABILITY_LOW 1
#define ITEM_SUITABILITY_MEDIUM 2
#define ITEM_SUITABILITY_HIGH 3
#define ITEM_SUITABILITY_ALWAYS 4
#define DEALER_BUYING 0
#define DEALER_SELLING 1
typedef struct
{
INT16 sItemIndex;
UINT8 ubOptimalNumber;
UINT32 uiIndex;
} DEALER_POSSIBLE_INV;
typedef struct
{
UINT32 uiItemClass;
UINT8 ubWeaponClass;
BOOLEAN fAllowUsed;
} ITEM_SORT_ENTRY;
INT8 GetDealersMaxItemAmount( UINT8 ubDealerID, UINT16 usItemIndex );
DEALER_POSSIBLE_INV *GetPointerToDealersPossibleInventory( UINT8 ubArmsDealerID );
UINT8 GetCurrentSuitabilityForItem( INT8 bArmsDealer, UINT16 usItemIndex );
UINT8 ChanceOfItemTransaction( INT8 bArmsDealer, UINT16 usItemIndex, BOOLEAN fDealerSelling, BOOLEAN fUsed );
BOOLEAN ItemTransactionOccurs( INT8 bArmsDealer, UINT16 usItemIndex, BOOLEAN fDealerSelling, BOOLEAN fUsed );
UINT8 DetermineInitialInvItems( INT8 bArmsDealerID, UINT16 usItemIndex, UINT8 ubChances, BOOLEAN fUsed);
UINT8 HowManyItemsAreSold( INT8 bArmsDealerID, UINT16 usItemIndex, UINT8 ubNumInStock, BOOLEAN fUsed);
UINT8 HowManyItemsToReorder(UINT8 ubWanted, UINT8 ubStillHave);
int BobbyRayItemQsortCompare(const void *pArg1, const void *pArg2);
int ArmsDealerItemQsortCompare(const void *pArg1, const void *pArg2);
int RepairmanItemQsortCompare(const void *pArg1, const void *pArg2);
int CompareItemsForSorting( UINT16 usItem1Index, UINT16 usItem2Index, UINT8 ubItem1Quality, UINT8 ubItem2Quality );
UINT8 GetDealerItemCategoryNumber( UINT16 usItemIndex );
BOOLEAN CanDealerItemBeSoldUsed( UINT16 usItemIndex );
extern DEALER_POSSIBLE_INV gTonyInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gDevinInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gFranzInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gKeithInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gSamInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gJakeInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gHowardInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gGabbyInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gFrankInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gElginInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gMannyInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gHerveInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gPeterInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gAlbertoInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gCarloInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gMickyInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gArnieInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gPerkoInventory[MAXITEMS+1];
extern DEALER_POSSIBLE_INV gFredoInventory[MAXITEMS+1];
#endif
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
#ifndef _AUTO_BANDAGE_H
#define _AUTO_BANDAGE_H
//#define VISIBLE_AUTO_BANDAGE
void AutoBandage( BOOLEAN fStart );
void BeginAutoBandage( );
BOOLEAN HandleAutoBandage( );
void ShouldBeginAutoBandage( );
void SetAutoBandagePending( BOOLEAN fSet );
void HandleAutoBandagePending( );
// ste the autobandage as complete
void SetAutoBandageComplete( void );
#endif
+514
View File
@@ -0,0 +1,514 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "Soldier Control.h"
#include "Overhead.h"
#include "Boxing.h"
#include "Render Fun.h"
#include "Random.h"
#include "Worldman.h"
#include "Soldier Profile.h"
#include "NPC.h"
#include "Opplist.h"
#include "ai.h"
#include "Dialogue Control.h"
#include "Handle UI.h"
#include "Points.h"
#include "interface.h"
#endif
INT16 gsBoxerGridNo[ NUM_BOXERS ] = { 11393, 11233, 11073 };
UINT8 gubBoxerID[ NUM_BOXERS ] = { NOBODY, NOBODY, NOBODY };
BOOLEAN gfBoxerFought[ NUM_BOXERS ] = { FALSE, FALSE, FALSE };
BOOLEAN gfLastBoxingMatchWonByPlayer = FALSE;
UINT8 gubBoxingMatchesWon = 0;
UINT8 gubBoxersRests = 0;
BOOLEAN gfBoxersResting = FALSE;
extern void RecalculateOppCntsDueToBecomingNeutral( SOLDIERTYPE * pSoldier );
void ExitBoxing( void )
{
UINT8 ubRoom;
SOLDIERTYPE * pSoldier;
UINT32 uiLoop;
UINT8 ubPass;
// find boxers and turn them neutral again
// first time through loop, look for AI guy, then for PC guy.... for stupid
// oppcnt/alert status reasons
for( ubPass = 0; ubPass < 2; ubPass++ )
{
// because boxer could die, loop through all soldier ptrs
for ( uiLoop = 0; uiLoop < gTacticalStatus.Team[ CIV_TEAM ].bLastID; uiLoop++ )
{
pSoldier = MercPtrs[ uiLoop ];
if ( pSoldier != NULL )
{
if ( ( pSoldier->uiStatusFlags & SOLDIER_BOXER ) && InARoom( pSoldier->sGridNo, &ubRoom ) && ubRoom == BOXING_RING )
{
if ( pSoldier->uiStatusFlags & SOLDIER_PC )
{
if ( ubPass == 0 ) // pass 0, only handle AI
{
continue;
}
// put guy under AI control temporarily
pSoldier->uiStatusFlags |= SOLDIER_PCUNDERAICONTROL;
}
else
{
if ( ubPass == 1 ) // pass 1, only handle PCs
{
continue;
}
// reset AI boxer to neutral
SetSoldierNeutral( pSoldier );
RecalculateOppCntsDueToBecomingNeutral( pSoldier );
}
CancelAIAction( pSoldier, TRUE );
pSoldier->bAlertStatus = STATUS_GREEN;
pSoldier->bUnderFire = 0;
// if necessary, revive boxer so he can leave ring
if (pSoldier->bLife > 0 && (pSoldier->bLife < OKLIFE || pSoldier->bBreath < OKBREATH ) )
{
pSoldier->bLife = __max( OKLIFE * 2, pSoldier->bLife );
if (pSoldier->bBreath < 100)
{
// deduct -ve BPs to grant some BPs back (properly)
DeductPoints( pSoldier, 0, (INT16) - ( (100 - pSoldier->bBreath) * 100 ) );
}
BeginSoldierGetup( pSoldier );
}
}
}
}
}
DeleteTalkingMenu();
EndAllAITurns();
if ( CheckForEndOfCombatMode( FALSE ) )
{
EndTopMessage();
SetMusicMode( MUSIC_TACTICAL_NOTHING );
// Lock UI until we get out of the ring
guiPendingOverrideEvent = LU_BEGINUILOCK;
}
}
// in both these cases we're going to want the AI to take over and move the boxers
// out of the ring!
void EndBoxingMatch( SOLDIERTYPE * pLoser )
{
if (pLoser->bTeam == gbPlayerNum )
{
SetBoxingState( LOST_ROUND );
}
else
{
SetBoxingState( WON_ROUND );
gfLastBoxingMatchWonByPlayer = TRUE;
gubBoxingMatchesWon++;
}
TriggerNPCRecord( DARREN, 22 );
}
void BoxingPlayerDisqualified( SOLDIERTYPE * pOffender, INT8 bReason )
{
if (bReason == BOXER_OUT_OF_RING || bReason == NON_BOXER_IN_RING)
{
EVENT_StopMerc( pOffender, pOffender->sGridNo, pOffender->bDirection );
}
SetBoxingState( DISQUALIFIED );
TriggerNPCRecord( DARREN, 21 );
//ExitBoxing();
}
void TriggerEndOfBoxingRecord( SOLDIERTYPE * pSoldier )
{
// unlock UI
guiPendingOverrideEvent = LU_ENDUILOCK;
if ( pSoldier )
{
switch( gTacticalStatus.bBoxingState )
{
case WON_ROUND:
AddHistoryToPlayersLog( HISTORY_WON_BOXING, pSoldier->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY );
TriggerNPCRecord( DARREN, 23 );
break;
case LOST_ROUND:
// log as lost
AddHistoryToPlayersLog( HISTORY_LOST_BOXING, pSoldier->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY );
TriggerNPCRecord( DARREN, 24 );
break;
case DISQUALIFIED:
AddHistoryToPlayersLog( HISTORY_DISQUALIFIED_BOXING, pSoldier->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY );
break;
}
}
SetBoxingState( NOT_BOXING );
}
UINT8 CountPeopleInBoxingRing( void )
{
SOLDIERTYPE * pSoldier;
UINT32 uiLoop;
UINT8 ubRoom;
UINT8 ubTotalInRing = 0;
for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ )
{
pSoldier = MercSlots[ uiLoop ];
if ( pSoldier != NULL )
{
if ( InARoom( pSoldier->sGridNo, &ubRoom ) && ubRoom == BOXING_RING)
{
ubTotalInRing++;
}
}
}
return( ubTotalInRing );
}
void CountPeopleInBoxingRingAndDoActions( void )
{
UINT32 uiLoop;
UINT8 ubTotalInRing = 0;
UINT8 ubRoom;
UINT8 ubPlayersInRing = 0;
SOLDIERTYPE * pSoldier;
SOLDIERTYPE * pInRing[2] = { NULL, NULL };
SOLDIERTYPE * pNonBoxingPlayer = NULL;
for ( uiLoop = 0; uiLoop < guiNumMercSlots; uiLoop++ )
{
pSoldier = MercSlots[ uiLoop ];
if ( pSoldier != NULL )
{
if ( InARoom( pSoldier->sGridNo, &ubRoom ) && ubRoom == BOXING_RING)
{
if ( ubTotalInRing < 2 )
{
pInRing[ ubTotalInRing ] = pSoldier;
}
ubTotalInRing++;
if ( pSoldier->uiStatusFlags & SOLDIER_PC )
{
ubPlayersInRing++;
if ( !pNonBoxingPlayer && !(pSoldier->uiStatusFlags & SOLDIER_BOXER) )
{
pNonBoxingPlayer = pSoldier;
}
}
}
}
}
if ( ubPlayersInRing > 1 )
{
// boxing match just became invalid!
if ( gTacticalStatus.bBoxingState <= PRE_BOXING )
{
BoxingPlayerDisqualified( pNonBoxingPlayer, NON_BOXER_IN_RING );
// set to not in boxing or it won't be handled otherwise
SetBoxingState( NOT_BOXING );
}
else
{
BoxingPlayerDisqualified( pNonBoxingPlayer, NON_BOXER_IN_RING );
}
return;
}
if ( gTacticalStatus.bBoxingState == BOXING_WAITING_FOR_PLAYER )
{
if ( ubTotalInRing == 1 && ubPlayersInRing == 1 )
{
// time to go to pre-boxing
SetBoxingState( PRE_BOXING );
PickABoxer();
}
}
else
// if pre-boxing, check for two people (from different teams!) in the ring
if ( gTacticalStatus.bBoxingState == PRE_BOXING )
{
if ( ubTotalInRing == 2 && ubPlayersInRing == 1 )
{
// ladieees and gennleman, we have a fight!
for ( uiLoop = 0; uiLoop < 2; uiLoop++ )
{
if ( ! ( pInRing[ uiLoop ]->uiStatusFlags & SOLDIER_BOXER ) )
{
// set as boxer!
pInRing[ uiLoop ]->uiStatusFlags |= SOLDIER_BOXER;
}
}
// start match!
SetBoxingState( BOXING );
gfLastBoxingMatchWonByPlayer = FALSE;
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Boxer APs %d %d", pInRing[0]->bActionPoints, pInRing[1]->bActionPoints );
#endif
// give the first turn to a randomly chosen boxer
EnterCombatMode( pInRing[ Random( 2 ) ]->bTeam );
}
}
/*
else
{
// check to see if the player has more than one person in the ring
if ( ubPlayersInRing > 1 )
{
// boxing match just became invalid!
BoxingPlayerDisqualified( pNonBoxingPlayer, NON_BOXER_IN_RING );
return;
}
}
*/
}
BOOLEAN CheckOnBoxers( void )
{
UINT32 uiLoop;
UINT8 ubID;
// repick boxer IDs every time
if ( gubBoxerID[0] == NOBODY )
{
// get boxer soldier IDs!
for( uiLoop = 0; uiLoop < NUM_BOXERS; uiLoop++ )
{
ubID = WhoIsThere2( gsBoxerGridNo[ uiLoop ], 0 );
if ( FindObjClass( MercPtrs[ ubID ], IC_WEAPON ) == NO_SLOT )
{
// no weapon so this guy is a boxer
gubBoxerID[ uiLoop ] = ubID;
}
}
}
if ( gubBoxerID[ 0 ] == NOBODY && gubBoxerID[ 1 ] == NOBODY && gubBoxerID[ 2 ] == NOBODY )
{
return( FALSE );
}
return( TRUE );
}
BOOLEAN BoxerExists( void )
{
UINT32 uiLoop;
for( uiLoop = 0; uiLoop < NUM_BOXERS; uiLoop++ )
{
if ( WhoIsThere2( gsBoxerGridNo[ uiLoop ], 0 ) != NOBODY )
{
return( TRUE );
}
}
return( FALSE );
}
BOOLEAN PickABoxer( void )
{
UINT32 uiLoop;
SOLDIERTYPE * pBoxer;
for( uiLoop = 0; uiLoop < NUM_BOXERS; uiLoop++ )
{
if ( gubBoxerID[ uiLoop ] != NOBODY )
{
if ( gfBoxerFought[ uiLoop ] )
{
// pathetic attempt to prevent multiple AI boxers
MercPtrs[ gubBoxerID[ uiLoop ] ]->uiStatusFlags &= ~SOLDIER_BOXER;
}
else
{
pBoxer = MercPtrs[ gubBoxerID[ uiLoop ] ];
// pick this boxer!
if ( pBoxer->bActive && pBoxer->bInSector && pBoxer->bLife >= OKLIFE )
{
pBoxer->uiStatusFlags |= SOLDIER_BOXER;
SetSoldierNonNeutral( pBoxer );
RecalculateOppCntsDueToNoLongerNeutral( pBoxer );
CancelAIAction( pBoxer, TRUE );
RESETTIMECOUNTER( pBoxer->AICounter, 0 );
gfBoxerFought[ uiLoop ] = TRUE;
// improve stats based on the # of rests these guys have had
pBoxer->bStrength = __min( 100, pBoxer->bStrength += gubBoxersRests * 5 );
pBoxer->bDexterity = __min( 100, pBoxer->bDexterity + gubBoxersRests * 5 );
pBoxer->bAgility = __min( 100, pBoxer->bAgility + gubBoxersRests * 5 );
pBoxer->bLifeMax = __min( 100, pBoxer->bLifeMax + gubBoxersRests * 5 );
// give the 3rd boxer martial arts
if ( (uiLoop == NUM_BOXERS - 1) && pBoxer->ubBodyType == REGMALE )
{
pBoxer->ubSkillTrait1 = MARTIALARTS;
}
return( TRUE );
}
}
}
}
return( FALSE );
}
BOOLEAN BoxerAvailable( void )
{
UINT8 ubLoop;
// No way around this, BoxerAvailable will have to go find boxer IDs if they aren't set.
if ( CheckOnBoxers() == FALSE )
{
return( FALSE );
}
for( ubLoop = 0; ubLoop < NUM_BOXERS; ubLoop++ )
{
if ( gubBoxerID[ ubLoop ] != NOBODY && !gfBoxerFought[ ubLoop ] )
{
return( TRUE );
}
}
return( FALSE );
}
// NOTE THIS IS NOW BROKEN BECAUSE NPC.C ASSUMES THAT BOXERSAVAILABLE < 3 IS A
// SEQUEL FIGHT. Maybe we could check Kingpin's location instead!
UINT8 BoxersAvailable( void )
{
UINT8 ubLoop;
UINT8 ubCount = 0;
for( ubLoop = 0; ubLoop < NUM_BOXERS; ubLoop++ )
{
if ( gubBoxerID[ ubLoop ] != NOBODY && !gfBoxerFought[ ubLoop ] )
{
ubCount++;
}
}
return( ubCount );
}
BOOLEAN AnotherFightPossible( void )
{
// Check that and a boxer is still available and
// a player has at least OKLIFE + 5 life
// and at least one fight HAS occurred
UINT8 ubLoop;
SOLDIERTYPE * pSoldier;
UINT8 ubAvailable;
ubAvailable = BoxersAvailable();
if ( ubAvailable == NUM_BOXERS || ubAvailable == 0 )
{
return( FALSE );
}
// Loop through all mercs on player team
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
pSoldier = MercPtrs[ ubLoop ];
for ( ; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++,pSoldier++ )
{
if ( pSoldier->bActive && pSoldier->bInSector && pSoldier->bLife > (OKLIFE + 5) && !pSoldier->bCollapsed )
{
return( TRUE );
}
}
return( FALSE );
}
void BoxingMovementCheck( SOLDIERTYPE * pSoldier )
{
UINT8 ubRoom;
if ( InARoom( pSoldier->sGridNo, &ubRoom ) && ubRoom == BOXING_RING)
{
// someone moving in/into the ring
CountPeopleInBoxingRingAndDoActions();
}
else if ( ( gTacticalStatus.bBoxingState == BOXING ) && ( pSoldier->uiStatusFlags & SOLDIER_BOXER ) )
{
// boxer stepped out of the ring!
BoxingPlayerDisqualified( pSoldier, BOXER_OUT_OF_RING );
// add the history record here.
AddHistoryToPlayersLog( HISTORY_DISQUALIFIED_BOXING, pSoldier->ubProfile, GetWorldTotalMin(), gWorldSectorX, gWorldSectorY );
// make not a boxer any more
pSoldier->uiStatusFlags &= ~(SOLDIER_BOXER);
pSoldier->uiStatusFlags &= (~SOLDIER_PCUNDERAICONTROL);
}
}
void SetBoxingState( INT8 bNewState )
{
if ( gTacticalStatus.bBoxingState == NOT_BOXING )
{
if ( bNewState != NOT_BOXING )
{
// pause time
PauseGame();
}
}
else
{
if ( bNewState == NOT_BOXING )
{
// unpause time
UnPauseGame();
if ( BoxersAvailable() == NUM_BOXERS )
{
// set one boxer to be set as boxed so that the game will allow another
// fight to occur
gfBoxerFought[ 0 ] = TRUE;
}
}
}
gTacticalStatus.bBoxingState = bNewState;
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_UI_FEEDBACK, L"Boxing state now %d", bNewState );
#endif
}
void ClearAllBoxerFlags( void )
{
UINT32 uiSlot;
for( uiSlot = 0; uiSlot < guiNumMercSlots; uiSlot++ )
{
if ( MercSlots[ uiSlot ] && MercSlots[ uiSlot ]->uiStatusFlags & SOLDIER_BOXER )
{
MercSlots[ uiSlot ]->uiStatusFlags &= ~(SOLDIER_BOXER);
}
}
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef BOXING_H
#define BOXING_H
#define BOXING_SECTOR_X 5
#define BOXING_SECTOR_Y 4
#define BOXING_SECTOR_Z 0
#define ROOM_SURROUNDING_BOXING_RING 3
#define BOXING_RING 29
#define BOXING_AI_START_POSITION 11235
#define NUM_BOXERS 3
enum DisqualificationReasons
{
BOXER_OUT_OF_RING,
NON_BOXER_IN_RING,
BAD_ATTACK
} ;
extern INT16 gsBoxerGridNo[ NUM_BOXERS ];
extern UINT8 gubBoxerID[ NUM_BOXERS ];
extern BOOLEAN gfBoxerFought[ NUM_BOXERS ];
extern INT8 gbBoxingState;
extern BOOLEAN gfLastBoxingMatchWonByPlayer;
extern UINT8 gubBoxingMatchesWon;
extern UINT8 gubBoxersRests;
extern BOOLEAN gfBoxersResting;
extern void BoxingPlayerDisqualified( SOLDIERTYPE * pOffender, INT8 bReason );
extern BOOLEAN PickABoxer( void );
extern BOOLEAN CheckOnBoxers( void );
extern void EndBoxingMatch( SOLDIERTYPE * pLoser );
extern BOOLEAN BoxerAvailable( void );
extern BOOLEAN AnotherFightPossible( void );
extern void TriggerEndOfBoxingRecord( SOLDIERTYPE * pSolier );
extern void BoxingMovementCheck( SOLDIERTYPE * pSoldier );
extern void ExitBoxing( void );
extern UINT8 BoxersAvailable( void );
extern void SetBoxingState( INT8 bNewState );
extern BOOLEAN BoxerExists( void );
extern UINT8 CountPeopleInBoxingRing( void );
extern void ClearAllBoxerFlags( void );
#endif
+89
View File
@@ -0,0 +1,89 @@
#ifndef __BULLETS_H
#define __BULLETS_H
#include "types.h"
#include "Soldier Control.h"
#include "los.h"
#include "tile animation.h"
#define BULLET_FLAG_CREATURE_SPIT 0x0001
#define BULLET_FLAG_KNIFE 0x0002
#define BULLET_FLAG_MISSILE 0x0004
#define BULLET_FLAG_SMALL_MISSILE 0x0008
#define BULLET_STOPPED 0x0010
#define BULLET_FLAG_TANK_CANNON 0x0020
#define BULLET_FLAG_BUCKSHOT 0x0040
#define BULLET_FLAG_FLAME 0x0080
typedef struct
{
INT32 iBullet;
UINT8 ubFirerID;
UINT8 ubTargetID;
INT8 bStartCubesAboveLevelZ;
INT8 bEndCubesAboveLevelZ;
UINT32 sGridNo;
INT16 sUnused;
UINT16 usLastStructureHit;
FIXEDPT qCurrX;
FIXEDPT qCurrY;
FIXEDPT qCurrZ;
FIXEDPT qIncrX;
FIXEDPT qIncrY;
FIXEDPT qIncrZ;
DOUBLE ddHorizAngle;
INT32 iCurrTileX;
INT32 iCurrTileY;
INT8 bLOSIndexX;
INT8 bLOSIndexY;
BOOLEAN fCheckForRoof;
INT32 iCurrCubesZ;
INT32 iLoop;
BOOLEAN fAllocated;
BOOLEAN fToDelete;
BOOLEAN fLocated;
BOOLEAN fReal;
BOOLEAN fAimed;
UINT32 uiLastUpdate;
UINT8 ubTilesPerUpdate;
UINT16 usClockTicksPerUpdate;
SOLDIERTYPE *pFirer;
UINT32 sTargetGridNo;
INT16 sHitBy;
INT32 iImpact;
INT32 iImpactReduction;
INT32 iRange;
INT32 iDistanceLimit;
UINT16 usFlags;
ANITILE *pAniTile;
ANITILE *pShadowAniTile;
UINT8 ubItemStatus;
UINT16 fromItem;
} BULLET;
extern UINT32 guiNumBullets;
INT32 CreateBullet( UINT8 ubFirer, BOOLEAN fFake, UINT16 usFlags,UINT16 fromItem );
void RemoveBullet( INT32 iBullet );
void StopBullet( INT32 iBullet );
void UpdateBullets( );
BULLET *GetBulletPtr( INT32 iBullet );
void DeleteAllBullets( );
void LocateBullet( INT32 iBulletIndex );
void HandleBulletSpecialFlags( INT32 iBulletIndex );
void AddMissileTrail( BULLET *pBullet, FIXEDPT qCurrX, FIXEDPT qCurrY, FIXEDPT qCurrZ );
//Save the bullet table to the saved game file
BOOLEAN SaveBulletStructureToSaveGameFile( HWFILE hFile );
//Load the bullet table from the saved game file
BOOLEAN LoadBulletStructureFromSavedGameFile( HWFILE hFile );
#endif
File diff suppressed because it is too large Load Diff
+89
View File
@@ -0,0 +1,89 @@
#ifndef __CAMPAIGN_H
#define __CAMPAIGN_H
#include "Soldier Profile.h"
#define SALARYAMT 0
#define HEALTHAMT 1
#define AGILAMT 2
#define DEXTAMT 3
#define WISDOMAMT 4
#define MEDICALAMT 5
#define EXPLODEAMT 6
#define MECHANAMT 7
#define MARKAMT 8
#define EXPERAMT 9
#define STRAMT 10
#define LDRAMT 11
#define ASSIGNAMT 12
#define NAMEAMT 13
#define FIRST_CHANGEABLE_STAT HEALTHAMT
#define LAST_CHANGEABLE_STAT LDRAMT
#define CHANGEABLE_STAT_COUNT ( LDRAMT - HEALTHAMT + 1 )
#define MAX_STAT_VALUE 100 // for stats and skills
#define MAXEXPLEVEL 10 // maximum merc experience level
#define SKILLS_SUBPOINTS_TO_IMPROVE 25
#define ATTRIBS_SUBPOINTS_TO_IMPROVE 50
#define LEVEL_SUBPOINTS_TO_IMPROVE 350 // per current level! (Can't go over 6500, 10x must fit in USHORT!)
#define WORKIMPROVERATE 2 // increase to make working mercs improve more
#define TRAINIMPROVERATE 2 // increase to make training mercs improve more
#define SALARY_CHANGE_PER_LEVEL 1.25 // Mercs salary is multiplied by this
#define MAX_DAILY_SALARY 30000 // must fit into an INT16 (32k)
#define MAX_LARGE_SALARY 500000 // no limit, really
// training cap: you can't train any stat/skill beyond this value
// Madd
#define TRAINING_RATING_CAP 100 // 85
// stat change causes
#define FROM_SUCCESS 0
#define FROM_TRAINING 1
#define FROM_FAILURE 2
// types of experience bonus awards
enum
{
EXP_BONUS_MINIMUM,
EXP_BONUS_SMALL,
EXP_BONUS_AVERAGE,
EXP_BONUS_LARGE,
EXP_BONUS_MAXIMUM,
NUM_EXP_BONUS_TYPES,
};
void StatChange(SOLDIERTYPE *pSoldier, UINT8 ubStat, UINT16 usNumChances, UINT8 ubReason);
void ProfileStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumChances, UINT8 ubReason);
void ProcessStatChange(MERCPROFILESTRUCT *pProfile, UINT8 ubStat, UINT16 usNumChances, UINT8 ubReason);
void UpdateStats( SOLDIERTYPE *pSoldier );
void ProfileUpdateStats( MERCPROFILESTRUCT *pProfile );
void ProcessUpdateStats( MERCPROFILESTRUCT *pProfile, SOLDIERTYPE *pSoldier );
UINT32 CalcNewSalary(UINT32 uiOldSalary, BOOLEAN fIncrease, UINT32 uiMaxLimit);
UINT32 RoundOffSalary(UINT32 uiSalary);
UINT16 SubpointsPerPoint(UINT8 ubStat, INT8 bExpLevel);
void HandleUnhiredMercImprovement( MERCPROFILESTRUCT *pProfile );
void HandleUnhiredMercDeaths( INT32 iProfileID );
UINT8 CurrentPlayerProgressPercentage(void);
UINT8 HighestPlayerProgressPercentage(void);
void HourlyProgressUpdate(void);
void HandleAnyStatChangesAfterAttack( void );
void AwardExperienceBonusToActiveSquad( UINT8 ubExpBonusType );
void BuildStatChangeString( STR16 wString, STR16 wName, BOOLEAN fIncrease, INT16 sPtsChanged, UINT8 ubStat );
void MERCMercWentUpALevelSendEmail( UINT8 ubMercMercIdValue );
#endif
+844
View File
@@ -0,0 +1,844 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#endif
#define DIALOGUE_DEFAULT_WIDTH 200
#define EXTREAMLY_LOW_TOWN_LOYALTY 20
#define HIGH_TOWN_LOYALTY 80
#define CIV_QUOTE_HINT 99
typedef struct
{
UINT8 ubNumEntries;
UINT8 ubUnusedCurrentEntry;
} CIV_QUOTE;
extern void CaptureTimerCallback( void );
BOOLEAN gfSurrendered = FALSE;
CIV_QUOTE gCivQuotes[ NUM_CIV_QUOTES ];
UINT8 gubNumEntries[ NUM_CIV_QUOTES ] =
{
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
5,
5,
15,
15,
15,
15,
15,
15,
15,
15,
15,
15,
2,
15,
15,
10,
10,
5,
3,
10,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3
};
typedef struct
{
BOOLEAN bActive;
MOUSE_REGION MouseRegion;
INT32 iVideoOverlay;
INT32 iDialogueBox;
UINT32 uiTimeOfCreation;
UINT32 uiDelayTime;
SOLDIERTYPE * pCiv;
} QUOTE_SYSTEM_STRUCT;
QUOTE_SYSTEM_STRUCT gCivQuoteData;
INT16 gzCivQuote[ 320 ];
UINT16 gusCivQuoteBoxWidth;
UINT16 gusCivQuoteBoxHeight;
void CopyNumEntriesIntoQuoteStruct( )
{
INT32 cnt;
for ( cnt = 0; cnt < NUM_CIV_QUOTES; cnt++ )
{
gCivQuotes[ cnt ].ubNumEntries = gubNumEntries[ cnt ];
}
}
BOOLEAN GetCivQuoteText( UINT8 ubCivQuoteID, UINT8 ubEntryID, INT16 *zQuote )
{
UINT8 zFileName[164];
// Build filename....
if ( ubCivQuoteID == CIV_QUOTE_HINT )
{
if ( gbWorldSectorZ > 0 )
{
//sprintf( zFileName, "NPCData\\miners.edt" );
sprintf( (char *)zFileName,"NPCDATA\\CIV%02d.edt", CIV_QUOTE_MINERS_NOT_FOR_PLAYER );
}
else
{
sprintf( (char *)zFileName, "NPCData\\%c%d.edt", 'A' + (gWorldSectorY - 1) , gWorldSectorX );
}
}
else
{
sprintf( (char *)zFileName,"NPCDATA\\CIV%02d.edt",ubCivQuoteID );
}
CHECKF( FileExists( (STR)zFileName ) );
// Get data...
LoadEncryptedDataFromFile( (STR)zFileName, (STR16)zQuote, ubEntryID * 320, 320 );
if( zQuote[0] == 0 )
{
return( FALSE );
}
return( TRUE );
}
void SurrenderMessageBoxCallBack( UINT8 ubExitValue )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt = 0;
if ( ubExitValue == MSG_BOX_RETURN_YES )
{
// CJC Dec 1 2002: fix multiple captures
BeginCaptureSquence();
// Do capture....
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++)
{
// Are we active and in sector.....
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector )
{
if ( pTeamSoldier->bLife != 0 )
{
EnemyCapturesPlayerSoldier( pTeamSoldier );
RemoveSoldierFromTacticalSector( pTeamSoldier, TRUE );
}
}
}
EndCaptureSequence( );
gfSurrendered = TRUE;
SetCustomizableTimerCallbackAndDelay( 3000, CaptureTimerCallback, FALSE );
ActionDone( gCivQuoteData.pCiv );
}
else
{
ActionDone( gCivQuoteData.pCiv );
}
}
void ShutDownQuoteBox( BOOLEAN fForce )
{
if ( !gCivQuoteData.bActive )
{
return;
}
// Check for min time....
if ( ( GetJA2Clock( ) - gCivQuoteData.uiTimeOfCreation ) > 300 || fForce )
{
RemoveVideoOverlay( gCivQuoteData.iVideoOverlay );
// Remove mouse region...
MSYS_RemoveRegion( &(gCivQuoteData.MouseRegion) );
RemoveMercPopupBoxFromIndex( gCivQuoteData.iDialogueBox );
gCivQuoteData.iDialogueBox = -1;
gCivQuoteData.bActive = FALSE;
// do we need to do anything at the end of the civ quote?
if ( gCivQuoteData.pCiv && gCivQuoteData.pCiv->bAction == AI_ACTION_OFFER_SURRENDER )
{
DoMessageBox( MSG_BOX_BASIC_STYLE, Message[ STR_SURRENDER ], GAME_SCREEN, ( UINT8 )MSG_BOX_FLAG_YESNO, SurrenderMessageBoxCallBack, NULL );
}
}
}
BOOLEAN ShutDownQuoteBoxIfActive( )
{
if ( gCivQuoteData.bActive )
{
ShutDownQuoteBox( TRUE );
return( TRUE );
}
return( FALSE );
}
INT8 GetCivType( SOLDIERTYPE *pCiv )
{
if ( pCiv->ubProfile != NO_PROFILE )
{
return( CIV_TYPE_NA );
}
// ATE: Check if this person is married.....
// 1 ) check sector....
if ( gWorldSectorX == 10 && gWorldSectorY == 6 && gbWorldSectorZ == 0 )
{
// 2 ) the only female....
if ( pCiv->ubCivilianGroup == 0 && pCiv->bTeam != gbPlayerNum && pCiv->ubBodyType == REGFEMALE )
{
// She's a ho!
return( CIV_TYPE_MARRIED_PC );
}
}
// OK, look for enemy type - MUST be on enemy team, merc bodytype
if ( pCiv->bTeam == ENEMY_TEAM && IS_MERC_BODY_TYPE( pCiv ) )
{
return( CIV_TYPE_ENEMY );
}
if ( pCiv->bTeam != CIV_TEAM && pCiv->bTeam != MILITIA_TEAM )
{
return( CIV_TYPE_NA );
}
switch( pCiv->ubBodyType )
{
case REGMALE:
case BIGMALE:
case STOCKYMALE:
case REGFEMALE:
case FATCIV:
case MANCIV:
case MINICIV:
case DRESSCIV:
case CRIPPLECIV:
return( CIV_TYPE_ADULT );
break;
case ADULTFEMALEMONSTER:
case AM_MONSTER:
case YAF_MONSTER:
case YAM_MONSTER:
case LARVAE_MONSTER:
case INFANT_MONSTER:
case QUEENMONSTER:
return( CIV_TYPE_NA );
case HATKIDCIV:
case KIDCIV:
return( CIV_TYPE_KID );
default:
return( CIV_TYPE_NA );
}
//return( CIV_TYPE_NA ); // not needed when there is a default! (jonathanl)
}
void RenderCivQuoteBoxOverlay( VIDEO_OVERLAY *pBlitter )
{
if ( gCivQuoteData.iVideoOverlay != -1 )
{
RenderMercPopUpBoxFromIndex( gCivQuoteData.iDialogueBox, pBlitter->sX, pBlitter->sY, pBlitter->uiDestBuff );
InvalidateRegion( pBlitter->sX, pBlitter->sY, pBlitter->sX + gusCivQuoteBoxWidth, pBlitter->sY + gusCivQuoteBoxHeight );
}
}
void QuoteOverlayClickCallback( MOUSE_REGION * pRegion, INT32 iReason )
{
static BOOLEAN fLButtonDown = FALSE;
if (iReason & MSYS_CALLBACK_REASON_LBUTTON_DWN )
{
fLButtonDown = TRUE;
}
if (iReason & MSYS_CALLBACK_REASON_LBUTTON_UP && fLButtonDown )
{
// Shutdown quote box....
ShutDownQuoteBox( FALSE );
}
else if (iReason & MSYS_CALLBACK_REASON_LOST_MOUSE )
{
fLButtonDown = FALSE;
}
}
void BeginCivQuote( SOLDIERTYPE *pCiv, UINT8 ubCivQuoteID, UINT8 ubEntryID, INT16 sX, INT16 sY )
{
VIDEO_OVERLAY_DESC VideoOverlayDesc;
INT16 zQuote[ 320 ];
// OK, do we have another on?
if ( gCivQuoteData.bActive )
{
// Delete?
ShutDownQuoteBox( TRUE );
}
// get text
if ( !GetCivQuoteText( ubCivQuoteID, ubEntryID, zQuote ) )
{
return;
}
#ifdef TAIWANESE
swprintf( (wchar_t *)gzCivQuote, (wchar_t *)L"%s", zQuote );
#else
swprintf( (wchar_t *)gzCivQuote, (wchar_t *)L"\"%s\"", zQuote );
#endif
if ( ubCivQuoteID == CIV_QUOTE_HINT )
{
MapScreenMessage( FONT_MCOLOR_WHITE, MSG_DIALOG, L"%s", gzCivQuote );
}
// Create video oeverlay....
memset( &VideoOverlayDesc, 0, sizeof( VIDEO_OVERLAY_DESC ) );
// Prepare text box
SET_USE_WINFONTS( TRUE );
SET_WINFONT( giSubTitleWinFont );
gCivQuoteData.iDialogueBox = PrepareMercPopupBox( gCivQuoteData.iDialogueBox , BASIC_MERC_POPUP_BACKGROUND, BASIC_MERC_POPUP_BORDER, (STR16)gzCivQuote, DIALOGUE_DEFAULT_WIDTH, 0, 0, 0, &gusCivQuoteBoxWidth, &gusCivQuoteBoxHeight );
SET_USE_WINFONTS( FALSE );
// OK, find center for box......
sX = sX - ( gusCivQuoteBoxWidth / 2 );
sY = sY - ( gusCivQuoteBoxHeight / 2 );
// OK, limit to screen......
{
if ( sX < 0 )
{
sX = 0;
}
// CHECK FOR LEFT/RIGHT
if ( ( sX + gusCivQuoteBoxWidth ) > 640 )
{
sX = 640 - gusCivQuoteBoxWidth;
}
// Now check for top
if ( sY < gsVIEWPORT_WINDOW_START_Y )
{
sY = gsVIEWPORT_WINDOW_START_Y;
}
// Check for bottom
if ( ( sY + gusCivQuoteBoxHeight ) > 340 )
{
sY = 340 - gusCivQuoteBoxHeight;
}
}
VideoOverlayDesc.sLeft = sX;
VideoOverlayDesc.sTop = sY;
VideoOverlayDesc.sRight = VideoOverlayDesc.sLeft + gusCivQuoteBoxWidth;
VideoOverlayDesc.sBottom = VideoOverlayDesc.sTop + gusCivQuoteBoxHeight;
VideoOverlayDesc.sX = VideoOverlayDesc.sLeft;
VideoOverlayDesc.sY = VideoOverlayDesc.sTop;
VideoOverlayDesc.BltCallback = RenderCivQuoteBoxOverlay;
gCivQuoteData.iVideoOverlay = RegisterVideoOverlay( 0, &VideoOverlayDesc );
//Define main region
MSYS_DefineRegion( &(gCivQuoteData.MouseRegion), VideoOverlayDesc.sLeft, VideoOverlayDesc.sTop, VideoOverlayDesc.sRight, VideoOverlayDesc.sBottom, MSYS_PRIORITY_HIGHEST,
CURSOR_NORMAL, MSYS_NO_CALLBACK, QuoteOverlayClickCallback );
// Add region
MSYS_AddRegion( &(gCivQuoteData.MouseRegion) );
gCivQuoteData.bActive = TRUE;
gCivQuoteData.uiTimeOfCreation = GetJA2Clock( );
gCivQuoteData.uiDelayTime = FindDelayForString( (STR16)gzCivQuote ) + 500;
gCivQuoteData.pCiv = pCiv;
}
UINT8 DetermineCivQuoteEntry( SOLDIERTYPE *pCiv, UINT8 *pubCivHintToUse, BOOLEAN fCanUseHints )
{
UINT8 ubCivType;
INT8 bTownId;
BOOLEAN bCivLowLoyalty = FALSE;
BOOLEAN bCivHighLoyalty = FALSE;
INT8 bCivHint;
INT8 bMineId;
BOOLEAN bMiners = FALSE;
(*pubCivHintToUse) = 0;
ubCivType = GetCivType( pCiv );
if ( ubCivType == CIV_TYPE_ENEMY )
{
// Determine what type of quote to say...
// Are are we going to attack?
if ( pCiv->bAction == AI_ACTION_TOSS_PROJECTILE || pCiv->bAction == AI_ACTION_FIRE_GUN ||
pCiv->bAction == AI_ACTION_FIRE_GUN || pCiv->bAction == AI_ACTION_KNIFE_MOVE )
{
return( CIV_QUOTE_ENEMY_THREAT );
}
else if ( pCiv->bAction == AI_ACTION_OFFER_SURRENDER )
{
return( CIV_QUOTE_ENEMY_OFFER_SURRENDER );
}
// Hurt?
else if ( pCiv->bLife < 30 )
{
return( CIV_QUOTE_ENEMY_HURT );
}
// elite?
else if ( pCiv->ubSoldierClass == SOLDIER_CLASS_ELITE )
{
return( CIV_QUOTE_ENEMY_ELITE );
}
else
{
return( CIV_QUOTE_ENEMY_ADMIN );
}
}
// Are we in a town sector?
// get town id
bTownId = GetTownIdForSector( gWorldSectorX, gWorldSectorY );
// If a married PC...
if ( ubCivType == CIV_TYPE_MARRIED_PC )
{
return( CIV_QUOTE_PC_MARRIED );
}
// CIV GROUPS FIRST!
// Hicks.....
if ( pCiv->ubCivilianGroup == HICKS_CIV_GROUP )
{
// Are they friendly?
//if ( gTacticalStatus.fCivGroupHostile[ HICKS_CIV_GROUP ] < CIV_GROUP_WILL_BECOME_HOSTILE )
if ( pCiv->bNeutral )
{
return( CIV_QUOTE_HICKS_FRIENDLY );
}
else
{
return( CIV_QUOTE_HICKS_ENEMIES );
}
}
// Goons.....
if ( pCiv->ubCivilianGroup == KINGPIN_CIV_GROUP )
{
// Are they friendly?
//if ( gTacticalStatus.fCivGroupHostile[ KINGPIN_CIV_GROUP ] < CIV_GROUP_WILL_BECOME_HOSTILE )
if ( pCiv->bNeutral )
{
return( CIV_QUOTE_GOONS_FRIENDLY );
}
else
{
return( CIV_QUOTE_GOONS_ENEMIES );
}
}
// ATE: Cowering people take precedence....
if ( ( pCiv->uiStatusFlags & SOLDIER_COWERING ) || ( pCiv->bTeam == CIV_TEAM && ( gTacticalStatus.uiFlags & INCOMBAT ) ) )
{
if ( ubCivType == CIV_TYPE_ADULT )
{
return( CIV_QUOTE_ADULTS_COWER );
}
else
{
return( CIV_QUOTE_KIDS_COWER );
}
}
// Kid slaves...
if ( pCiv->ubCivilianGroup == FACTORY_KIDS_GROUP )
{
// Check fact.....
if ( CheckFact( FACT_DOREEN_HAD_CHANGE_OF_HEART, 0 ) || !CheckFact( FACT_DOREEN_ALIVE, 0 ) )
{
return( CIV_QUOTE_KID_SLAVES_FREE );
}
else
{
return( CIV_QUOTE_KID_SLAVES );
}
}
// BEGGERS
if ( pCiv->ubCivilianGroup == BEGGARS_CIV_GROUP )
{
// Check if we are in a town...
if( bTownId != BLANK_SECTOR && gbWorldSectorZ == 0 )
{
if ( bTownId == SAN_MONA && ubCivType == CIV_TYPE_ADULT )
{
return( CIV_QUOTE_SAN_MONA_BEGGERS );
}
}
// DO normal beggers...
if ( ubCivType == CIV_TYPE_ADULT )
{
return( CIV_QUOTE_ADULTS_BEGGING );
}
else
{
return( CIV_QUOTE_KIDS_BEGGING );
}
}
// REBELS
if ( pCiv->ubCivilianGroup == REBEL_CIV_GROUP )
{
// DO normal beggers...
if ( ubCivType == CIV_TYPE_ADULT )
{
return( CIV_QUOTE_ADULTS_REBELS );
}
else
{
return( CIV_QUOTE_KIDS_REBELS );
}
}
// Do miltitia...
if ( pCiv->bTeam == MILITIA_TEAM )
{
// Different types....
if ( pCiv->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
{
return( CIV_QUOTE_GREEN_MILITIA );
}
if ( pCiv->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
{
return( CIV_QUOTE_MEDIUM_MILITIA );
}
if ( pCiv->ubSoldierClass == SOLDIER_CLASS_ELITE_MILITIA )
{
return( CIV_QUOTE_ELITE_MILITIA );
}
}
// If we are in medunna, and queen is dead, use these...
if ( bTownId == MEDUNA && CheckFact( FACT_QUEEN_DEAD, 0 ) )
{
return( CIV_QUOTE_DEIDRANNA_DEAD );
}
// if in a town
if( ( bTownId != BLANK_SECTOR ) && ( gbWorldSectorZ == 0 ) && gfTownUsesLoyalty[ bTownId ] )
{
// Check loyalty special quotes.....
// EXTREMELY LOW TOWN LOYALTY...
if ( gTownLoyalty[ bTownId ].ubRating < EXTREAMLY_LOW_TOWN_LOYALTY )
{
bCivLowLoyalty = TRUE;
}
// HIGH TOWN LOYALTY...
if ( gTownLoyalty[ bTownId ].ubRating >= HIGH_TOWN_LOYALTY )
{
bCivHighLoyalty = TRUE;
}
}
// ATE: OK, check if we should look for a civ hint....
if ( fCanUseHints )
{
bCivHint = ConsiderCivilianQuotes( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, FALSE );
}
else
{
bCivHint = -1;
}
// ATE: check miners......
if ( pCiv->ubSoldierClass == SOLDIER_CLASS_MINER )
{
bMiners = TRUE;
// If not a civ hint available...
if ( bCivHint == -1 )
{
// Check if they are under our control...
// Should I go talk to miner?
// Not done yet.
// Are they working for us?
bMineId = GetIdOfMineForSector( gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
if ( PlayerControlsMine( bMineId ) )
{
return( CIV_QUOTE_MINERS_FOR_PLAYER );
}
else
{
return( CIV_QUOTE_MINERS_NOT_FOR_PLAYER );
}
}
}
// Is one availible?
// If we are to say low loyalty, do chance
if ( bCivHint != -1 && bCivLowLoyalty && !bMiners )
{
if ( Random( 100 ) < 25 )
{
// Get rid of hint...
bCivHint = -1;
}
}
// Say hint if availible...
if ( bCivHint != -1 )
{
if ( ubCivType == CIV_TYPE_ADULT )
{
(*pubCivHintToUse) = bCivHint;
// Set quote as used...
ConsiderCivilianQuotes( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE );
// retrun value....
return( CIV_QUOTE_HINT );
}
}
if ( bCivLowLoyalty )
{
if ( ubCivType == CIV_TYPE_ADULT )
{
return( CIV_QUOTE_ADULTS_EXTREMLY_LOW_LOYALTY );
}
else
{
return( CIV_QUOTE_KIDS_EXTREMLY_LOW_LOYALTY );
}
}
if ( bCivHighLoyalty )
{
if ( ubCivType == CIV_TYPE_ADULT )
{
return( CIV_QUOTE_ADULTS_HIGH_LOYALTY );
}
else
{
return( CIV_QUOTE_KIDS_HIGH_LOYALTY );
}
}
// All purpose quote here....
if ( ubCivType == CIV_TYPE_ADULT )
{
return( CIV_QUOTE_ADULTS_ALL_PURPOSE );
}
else
{
return( CIV_QUOTE_KIDS_ALL_PURPOSE );
}
}
void HandleCivQuote( )
{
if ( gCivQuoteData.bActive )
{
// Check for min time....
if ( ( GetJA2Clock( ) - gCivQuoteData.uiTimeOfCreation ) > gCivQuoteData.uiDelayTime )
{
// Stop!
ShutDownQuoteBox( TRUE );
}
}
}
void StartCivQuote( SOLDIERTYPE *pCiv )
{
UINT8 ubCivQuoteID;
INT16 sX, sY;
UINT8 ubEntryID = 0;
INT16 sScreenX, sScreenY;
UINT8 ubCivHintToUse;
// ATE: Check for old quote.....
// This could have been stored on last attempt...
if ( pCiv->bCurrentCivQuote == CIV_QUOTE_HINT )
{
// Determine which quote to say.....
// CAN'T USE HINTS, since we just did one...
pCiv->bCurrentCivQuote = -1;
pCiv->bCurrentCivQuoteDelta = 0;
ubCivQuoteID = DetermineCivQuoteEntry( pCiv, &ubCivHintToUse, FALSE );
}
else
{
// Determine which quote to say.....
ubCivQuoteID = DetermineCivQuoteEntry( pCiv, &ubCivHintToUse, TRUE );
}
// Determine entry id
// ATE: Try and get entry from soldier pointer....
if ( ubCivQuoteID != CIV_QUOTE_HINT )
{
if ( pCiv->bCurrentCivQuote == -1 )
{
// Pick random one
pCiv->bCurrentCivQuote = (INT8)Random( gCivQuotes[ ubCivQuoteID ].ubNumEntries - 2 );
pCiv->bCurrentCivQuoteDelta = 0;
}
ubEntryID = pCiv->bCurrentCivQuote + pCiv->bCurrentCivQuoteDelta;
}
else
{
ubEntryID = ubCivHintToUse;
// ATE: set value for quote ID.....
pCiv->bCurrentCivQuote = ubCivQuoteID;
pCiv->bCurrentCivQuoteDelta = ubEntryID;
}
// Determine location...
// Get location of civ on screen.....
GetSoldierScreenPos( pCiv, &sScreenX, &sScreenY );
sX = sScreenX;
sY = sScreenY;
// begin quote
BeginCivQuote( pCiv, ubCivQuoteID, ubEntryID, sX, sY );
// Increment use
if ( ubCivQuoteID != CIV_QUOTE_HINT )
{
pCiv->bCurrentCivQuoteDelta++;
if ( pCiv->bCurrentCivQuoteDelta == 2 )
{
pCiv->bCurrentCivQuoteDelta = 0;
}
}
}
void InitCivQuoteSystem( )
{
memset( &gCivQuotes, 0, sizeof( gCivQuotes ) );
CopyNumEntriesIntoQuoteStruct( );
memset( &gCivQuoteData, 0, sizeof( gCivQuoteData ) );
gCivQuoteData.bActive = FALSE;
gCivQuoteData.iVideoOverlay = -1;
gCivQuoteData.iDialogueBox = -1;
}
BOOLEAN SaveCivQuotesToSaveGameFile( HWFILE hFile )
{
UINT32 uiNumBytesWritten;
FileWrite( hFile, &gCivQuotes, sizeof( gCivQuotes ), &uiNumBytesWritten );
if( uiNumBytesWritten != sizeof( gCivQuotes ) )
{
return( FALSE );
}
return( TRUE );
}
BOOLEAN LoadCivQuotesFromLoadGameFile( HWFILE hFile )
{
UINT32 uiNumBytesRead;
FileRead( hFile, &gCivQuotes, sizeof( gCivQuotes ), &uiNumBytesRead );
if( uiNumBytesRead != sizeof( gCivQuotes ) )
{
return( FALSE );
}
CopyNumEntriesIntoQuoteStruct( );
return( TRUE );
}
+87
View File
@@ -0,0 +1,87 @@
#ifndef __CIV_QUOTES_H
#define __CIV_QUOTES_H
#define CIV_TYPE_NA 0
#define CIV_TYPE_ADULT 1
#define CIV_TYPE_KID 2
#define CIV_TYPE_MARRIED_PC 3
#define CIV_TYPE_ENEMY 4
enum
{
CIV_QUOTE_ADULTS_BEGGING,
CIV_QUOTE_KIDS_BEGGING,
CIV_QUOTE_ADULTS_RECENT_BUG_ATTACK,
CIV_QUOTE_KIDS_RECENT_BUG_ATTACK,
CIV_QUOTE_ADULTS_BUG_EXTERMINATED_X_TIME,
CIV_QUOTE_KIDS_BUG_EXTERMINATED_X_TIME,
CIV_QUOTE_ADULTS_EXTREMLY_LOW_LOYALTY,
CIV_QUOTE_KIDS_EXTREMLY_LOW_LOYALTY,
CIV_QUOTE_ADULTS_HIGH_LOYALTY,
CIV_QUOTE_KIDS_HIGH_LOYALTY,
CIV_QUOTE_ADULTS_ALL_PURPOSE,
CIV_QUOTE_KIDS_ALL_PURPOSE,
CIV_QUOTE_ADULTS_LIBREATED_FIRST_TIME,
CIV_QUOTE_KIDS_LIBREATED_FIRST_TIME,
CIV_QUOTE_ADULTS_TOWN_TAKEN_BACK,
CIV_QUOTE_KIDS_TOWN_TAKEN_BACK,
CIV_QUOTE_HICKS_FRIENDLY,
CIV_QUOTE_HICKS_ENEMIES,
CIV_QUOTE_GOONS_FRIENDLY,
CIV_QUOTE_GOONS_ENEMIES,
CIV_QUOTE_ADULTS_REBELS,
CIV_QUOTE_KIDS_REBELS,
CIV_QUOTE_GREEN_MILITIA,
CIV_QUOTE_MEDIUM_MILITIA,
CIV_QUOTE_ELITE_MILITIA,
CIV_QUOTE_SAN_MONA_BEGGERS,
CIV_QUOTE_ENEMY_HURT,
CIV_QUOTE_ENEMY_ADMIN,
CIV_QUOTE_ENEMY_THREAT,
CIV_QUOTE_ENEMY_ELITE,
CIV_QUOTE_ADULTS_COWER,
CIV_QUOTE_KIDS_COWER,
CIV_QUOTE_PC_MARRIED,
CIV_QUOTE_KID_SLAVES,
CIV_QUOTE_KID_SLAVES_FREE,
CIV_QUOTE_MINERS_NOT_FOR_PLAYER,
CIV_QUOTE_MINERS_FOR_PLAYER,
CIV_QUOTE_ENEMY_OFFER_SURRENDER,
CIV_QUOTE_HICKS_SEE_US_AT_NIGHT,
CIV_QUOTE_DEIDRANNA_DEAD,
CIV_QUOTE_40,
CIV_QUOTE_41,
CIV_QUOTE_42,
CIV_QUOTE_43,
CIV_QUOTE_44,
CIV_QUOTE_45,
CIV_QUOTE_46,
CIV_QUOTE_47,
CIV_QUOTE_48,
CIV_QUOTE_49,
NUM_CIV_QUOTES
};
void InitCivQuoteSystem( );
void StartCivQuote( SOLDIERTYPE *pCiv );
INT8 GetCivType( SOLDIERTYPE *pCiv );
void HandleCivQuote( );
BOOLEAN SaveCivQuotesToSaveGameFile( HWFILE hFile );
BOOLEAN LoadCivQuotesFromLoadGameFile( HWFILE hFile );
BOOLEAN ShutDownQuoteBoxIfActive( );
void BeginCivQuote( SOLDIERTYPE *pCiv, UINT8 ubCivQuoteID, UINT8 ubEntryID, INT16 sX, INT16 sY );
#endif
File diff suppressed because it is too large Load Diff
+350
View File
@@ -0,0 +1,350 @@
#ifndef _DIALOG_CONTROL_H
#define _DIALOG_CONTROL_H
#include "faces.h"
#include "gamescreen.h"
// An enumeration for dialog quotes
enum DialogQuoteIDs
{
// 0
QUOTE_SEE_ENEMY = 0,
QUOTE_SEE_ENEMY_VARIATION,
QUOTE_IN_TROUBLE_SLASH_IN_BATTLE,
QUOTE_SEE_CREATURE,
QUOTE_FIRSTTIME_GAME_SEE_CREATURE,
QUOTE_TRACES_OF_CREATURE_ATTACK,
QUOTE_HEARD_SOMETHING,
QUOTE_SMELLED_CREATURE,
QUOTE_WEARY_SLASH_SUSPUCIOUS,
QUOTE_WORRIED_ABOUT_CREATURE_PRESENCE,
//10
QUOTE_ATTACKED_BY_MULTIPLE_CREATURES,
QUOTE_SPOTTED_SOMETHING_ONE,
QUOTE_SPOTTED_SOMETHING_TWO,
QUOTE_OUT_OF_AMMO,
QUOTE_SERIOUSLY_WOUNDED,
QUOTE_BUDDY_ONE_KILLED,
QUOTE_BUDDY_TWO_KILLED,
QUOTE_LEARNED_TO_LIKE_MERC_KILLED,
QUOTE_FORGETFULL_SLASH_CONFUSED,
QUOTE_JAMMED_GUN,
//20
QUOTE_UNDER_HEAVY_FIRE,
QUOTE_TAKEN_A_BREATING,
QUOTE_CLOSE_CALL,
QUOTE_NO_LINE_OF_FIRE,
QUOTE_STARTING_TO_BLEED,
QUOTE_NEED_SLEEP,
QUOTE_OUT_OF_BREATH,
QUOTE_KILLED_AN_ENEMY,
QUOTE_KILLED_A_CREATURE,
QUOTE_HATED_MERC_ONE,
//30
QUOTE_HATED_MERC_TWO,
QUOTE_LEARNED_TO_HATE_MERC,
QUOTE_AIM_KILLED_MIKE,
QUOTE_MERC_QUIT_LEARN_TO_HATE = QUOTE_AIM_KILLED_MIKE,
QUOTE_HEADSHOT,
QUOTE_PERSONALITY_TRAIT,
QUOTE_ASSIGNMENT_COMPLETE,
QUOTE_REFUSING_ORDER,
QUOTE_KILLING_DEIDRANNA,
QUOTE_KILLING_QUEEN,
QUOTE_ANNOYING_PC,
//40
QUOTE_STARTING_TO_WHINE,
QUOTE_NEGATIVE_COMPANY,
QUOTE_AIR_RAID,
QUOTE_WHINE_EQUIPMENT,
QUOTE_SOCIAL_TRAIT,
QUOTE_PASSING_DISLIKE,
QUOTE_EXPERIENCE_GAIN,
QUOTE_PRE_NOT_SMART,
QUOTE_POST_NOT_SMART,
QUOTE_HATED_1_ARRIVES,
QUOTE_MERC_QUIT_HATED1 = QUOTE_HATED_1_ARRIVES,
//50
QUOTE_HATED_2_ARRIVES,
QUOTE_MERC_QUIT_HATED2 = QUOTE_HATED_2_ARRIVES,
QUOTE_BUDDY_1_GOOD,
QUOTE_BUDDY_2_GOOD,
QUOTE_LEARNED_TO_LIKE_WITNESSED,
QUOTE_DELAY_CONTRACT_RENEWAL,
QUOTE_NOT_GETTING_PAID = QUOTE_DELAY_CONTRACT_RENEWAL,
QUOTE_AIM_SEEN_MIKE,
QUOTE_PC_DROPPED_OMERTA = QUOTE_AIM_SEEN_MIKE,
QUOTE_BLINDED,
QUOTE_DEFINITE_CANT_DO,
QUOTE_LISTEN_LIKABLE_PERSON,
QUOTE_ENEMY_PRESENCE,
//60
QUOTE_WARNING_OUTSTANDING_ENEMY_AFTER_RT,
QUOTE_FOUND_SOMETHING_SPECIAL,
QUOTE_SATISFACTION_WITH_GUN_AFTER_KILL,
QUOTE_SPOTTED_JOEY,
QUOTE_RESPONSE_TO_MIGUEL_SLASH_QUOTE_MERC_OR_RPC_LETGO,
QUOTE_SECTOR_SAFE,
QUOTE_STUFF_MISSING_DRASSEN,
QUOTE_KILLED_FACTORY_MANAGER,
QUOTE_SPOTTED_BLOODCAT,
QUOTE_END_GAME_COMMENT,
//70
QUOTE_ENEMY_RETREATED,
QUOTE_GOING_TO_AUTO_SLEEP,
QUOTE_WORK_UP_AND_RETURNING_TO_ASSIGNMENT, // woke up from auto sleep, going back to wo
QUOTE_ME_TOO, // me too quote, in agreement with whatever the merc previous said
QUOTE_USELESS_ITEM,
QUOTE_BOOBYTRAP_ITEM,
QUOTE_SUSPICIOUS_GROUND,
QUOTE_DROWNING,
QUOTE_MERC_REACHED_DESTINATION,
QUOTE_SPARE2,
//80
QUOTE_REPUTATION_REFUSAL,
QUOTE_DEATH_RATE_REFUSAL, //= 99,
QUOTE_LAME_REFUSAL, //= 82,
QUOTE_WONT_RENEW_CONTRACT_LAME_REFUSAL, // ARM: now unused
QUOTE_ANSWERING_MACHINE_MSG,
QUOTE_DEPARTING_COMMENT_CONTRACT_NOT_RENEWED_OR_48_OR_MORE,
QUOTE_HATE_MERC_1_ON_TEAM,// = 100,
QUOTE_HATE_MERC_2_ON_TEAM,// = 101,
QUOTE_LEARNED_TO_HATE_MERC_ON_TEAM,// = 102,
QUOTE_CONTRACTS_OVER,// = 89,
//90
QUOTE_ACCEPT_CONTRACT_RENEWAL,
QUOTE_CONTRACT_ACCEPTANCE,
QUOTE_JOINING_CAUSE_BUDDY_1_ON_TEAM,// = 103,
QUOTE_JOINING_CAUSE_BUDDY_2_ON_TEAM,// = 104,
QUOTE_JOINING_CAUSE_LEARNED_TO_LIKE_BUDDY_ON_TEAM,// = 105,
QUOTE_REFUSAL_RENEW_DUE_TO_MORALE,// = 95,
QUOTE_PRECEDENT_TO_REPEATING_ONESELF,// = 106,
QUOTE_REFUSAL_TO_JOIN_LACK_OF_FUNDS,// = 107,
QUOTE_DEPART_COMMET_CONTRACT_NOT_RENEWED_OR_TERMINATED_UNDER_48,// = 98,
QUOTE_DEATH_RATE_RENEWAL,
//100
QUOTE_HATE_MERC_1_ON_TEAM_WONT_RENEW,
QUOTE_HATE_MERC_2_ON_TEAM_WONT_RENEW,
QUOTE_LEARNED_TO_HATE_MERC_1_ON_TEAM_WONT_RENEW,
QUOTE_RENEWING_CAUSE_BUDDY_1_ON_TEAM,
QUOTE_RENEWING_CAUSE_BUDDY_2_ON_TEAM,
QUOTE_RENEWING_CAUSE_LEARNED_TO_LIKE_BUDDY_ON_TEAM,
QUOTE_PRECEDENT_TO_REPEATING_ONESELF_RENEW,
QUOTE_RENEW_REFUSAL_DUE_TO_LACK_OF_FUNDS,
QUOTE_GREETING,
QUOTE_SMALL_TALK,
//110
QUOTE_IMPATIENT_QUOTE,
QUOTE_LENGTH_OF_CONTRACT,
QUOTE_COMMENT_BEFORE_HANG_UP,
QUOTE_PERSONALITY_BIAS_WITH_MERC_1,
QUOTE_PERSONALITY_BIAS_WITH_MERC_2,
QUOTE_MERC_LEAVING_ALSUCO_SOON,
QUOTE_MERC_GONE_UP_IN_PRICE,
} ;
#define DEFAULT_EXTERN_PANEL_X_POS 320
#define DEFAULT_EXTERN_PANEL_Y_POS 40
#define DIALOGUE_TACTICAL_UI 1
#define DIALOGUE_CONTACTPAGE_UI 2
#define DIALOGUE_NPC_UI 3
#define DIALOGUE_SPECK_CONTACT_PAGE_UI 4
#define DIALOGUE_EXTERNAL_NPC_UI 5
#define DIALOGUE_SHOPKEEPER_UI 6
#define DIALOGUE_SPECIAL_EVENT_GIVE_ITEM 0x00000001
#define DIALOGUE_SPECIAL_EVENT_TRIGGER_NPC 0x00000002
#define DIALOGUE_SPECIAL_EVENT_GOTO_GRIDNO 0x00000004
#define DIALOGUE_SPECIAL_EVENT_DO_ACTION 0x00000008
#define DIALOGUE_SPECIAL_EVENT_CLOSE_PANEL 0x00000010
#define DIALOGUE_SPECIAL_EVENT_PCTRIGGERNPC 0x00000020
#define DIALOGUE_SPECIAL_EVENT_BEGINPREBATTLEINTERFACE 0x00000040
#define DIALOGUE_SPECIAL_EVENT_SKYRIDERMAPSCREENEVENT 0x00000080
#define DIALOGUE_SPECIAL_EVENT_SHOW_CONTRACT_MENU 0x00000100
#define DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT 0x00000200
#define DIALOGUE_SPECIAL_EVENT_SHOW_UPDATE_MENU 0x00000400
#define DIALOGUE_SPECIAL_EVENT_ENABLE_AI 0x00000800
#define DIALOGUE_SPECIAL_EVENT_USE_ALTERNATE_FILES 0x00001000
#define DIALOGUE_SPECIAL_EVENT_CONTINUE_TRAINING_MILITIA 0x00002000
#define DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING 0x00004000
#define DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE 0x00008000
#define DIALOGUE_SPECIAL_EVENT_SLEEP 0x00010000
#define DIALOGUE_SPECIAL_EVENT_DO_BATTLE_SND 0x00020000
#define DIALOGUE_SPECIAL_EVENT_SIGNAL_ITEM_LOCATOR_START 0x00040000
#define DIALOGUE_SPECIAL_EVENT_SHOPKEEPER 0x00080000
#define DIALOGUE_SPECIAL_EVENT_SKIP_A_FRAME 0x00100000
#define DIALOGUE_SPECIAL_EVENT_EXIT_MAP_SCREEN 0x00200000
#define DIALOGUE_SPECIAL_EVENT_DISPLAY_STAT_CHANGE 0x00400000
#define DIALOGUE_SPECIAL_EVENT_UNSET_ARRIVES_FLAG 0x00800000
#define DIALOGUE_SPECIAL_EVENT_TRIGGERPREBATTLEINTERFACE 0x01000000
#define DIALOGUE_ADD_EVENT_FOR_SOLDIER_UPDATE_BOX 0x02000000
#define DIALOGUE_SPECIAL_EVENT_ENTER_MAPSCREEN 0x04000000
#define DIALOGUE_SPECIAL_EVENT_LOCK_INTERFACE 0x08000000
#define DIALOGUE_SPECIAL_EVENT_REMOVE_EPC 0x10000000
#define DIALOGUE_SPECIAL_EVENT_CONTRACT_WANTS_TO_RENEW 0x20000000
#define DIALOGUE_SPECIAL_EVENT_CONTRACT_NOGO_TO_RENEW 0x40000000
#define DIALOGUE_SPECIAL_EVENT_CONTRACT_ENDING_NO_ASK_EQUIP 0x80000000
#define MULTIPURPOSE_SPECIAL_EVENT_DONE_KILLING_DEIDRANNA 0x00000001
#define MULTIPURPOSE_SPECIAL_EVENT_TEAM_MEMBERS_DONE_TALKING 0x00000002
enum{
SKYRIDER_EXTERNAL_FACE =0,
MINER_FRED_EXTERNAL_FACE,
MINER_MATT_EXTERNAL_FACE,
MINER_OSWALD_EXTERNAL_FACE,
MINER_CALVIN_EXTERNAL_FACE,
MINER_CARL_EXTERNAL_FACE,
NUMBER_OF_EXTERNAL_NPC_FACES,
};
// soldier up-date box reasons
enum{
UPDATE_BOX_REASON_ADDSOLDIER =0,
UPDATE_BOX_REASON_SET_REASON,
UPDATE_BOX_REASON_SHOW_BOX,
};
extern UINT32 uiExternalStaticNPCFaces[ ];
extern UINT32 uiExternalFaceProfileIds[ ];
// Functions for handling dialogue Q
BOOLEAN InitalizeDialogueControl();
void ShutdownDialogueControl();
void EmptyDialogueQueue( );
void HandleDialogue( );
void HandleImportantMercQuote( SOLDIERTYPE * pSoldier, UINT16 usQuoteNumber );
// Send in a profile number to see if text dialog exists for this guy....
BOOLEAN DialogueDataFileExistsForProfile( UINT8 ubCharacterNum, UINT16 usQuoteNum, BOOLEAN fWavFile, UINT8 **ppStr );
// Do special event as well as dialogue!
BOOLEAN CharacterDialogueWithSpecialEvent( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fFromSoldier, BOOLEAN fDelayed, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2 );
// Do special event as well as dialogue!
BOOLEAN CharacterDialogueWithSpecialEventEx( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fFromSoldier, BOOLEAN fDelayed, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 );
// A higher level function used for tactical quotes
BOOLEAN TacticalCharacterDialogueWithSpecialEvent( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2 );
// A higher level function used for tactical quotes
BOOLEAN TacticalCharacterDialogueWithSpecialEventEx( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum, UINT32 uiFlag, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 );
// A higher level function used for tactical quotes
BOOLEAN TacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum );
// A higher level function used for tactical quotes
BOOLEAN DelayedTacticalCharacterDialogue( SOLDIERTYPE *pSoldier, UINT16 usQuoteNum );
// A more general purpose function for processing quotes
BOOLEAN CharacterDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fFromSoldier, BOOLEAN fDelayed );
// A special event can be setup which can be queued with other speech
BOOLEAN SpecialCharacterDialogueEvent( UINT32 uiSpecialEventFlag, UINT32 uiSpecialEventData1, UINT32 uiSpecialEventData2, UINT32 uiSpecialEventData3, INT32 iFaceIndex, UINT8 bUIHandlerID );
// Same as above, for triggers, with extra param to hold approach value
BOOLEAN SpecialCharacterDialogueEventWithExtraParam( UINT32 uiSpecialEventFlag, UINT32 uiSpecialEventData1, UINT32 uiSpecialEventData2, UINT32 uiSpecialEventData3, UINT32 uiSpecialEventData4, INT32 iFaceIndex, UINT8 bUIHandlerID );
// execute specific character dialogue
BOOLEAN ExecuteCharacterDialogue( UINT8 ubCharacterNum, UINT16 usQuoteNum, INT32 iFaceIndex, UINT8 bUIHandlerID, BOOLEAN fSoldier );
// Called when a face stops talking...
void HandleDialogueEnd( FACETYPE *pFace );
// shut down last quotetext box
void ShutDownLastQuoteTacticalTextBox( void );
// Called to advance speech
// Used for option when no speech sound file
void DialogueAdvanceSpeech( );
BOOLEAN DialogueQueueIsEmpty( );
BOOLEAN DialogueQueueIsEmptyOrSomebodyTalkingNow( );
// Adjust the face, etc when switching from panel to extern panel...
void HandleDialogueUIAdjustments( );
// pause game time during
void PauseTimeDuringNextQuote( );
void UnPauseGameDuringNextQuote( void );
// set up and shutdown static external NPC faces
void InitalizeStaticExternalNPCFaces( void );
void ShutdownStaticExternalNPCFaces( void );
void SayQuoteFromAnyBodyInSector( UINT16 usQuoteNum );
void SayQuoteFromAnyBodyInThisSector( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT16 usQuoteNum );
void SayQuoteFromNearbyMercInSector( INT16 sGridNo, INT8 bDistance, UINT16 usQuoteNum );
void SayQuote58FromNearbyMercInSector( INT16 sGridNo, INT8 bDistance, UINT16 usQuoteNum, INT8 bSex );
void ExecuteTacticalTextBox( INT16 sLeftPosition, STR16 pString );
void ExecuteTacticalTextBoxForLastQuote( INT16 sLeftPosition, STR16 pString );
UINT32 FindDelayForString( STR16 sString );
void BeginLoggingForBleedMeToos( BOOLEAN fStart );
void UnSetEngagedInConvFromPCAction( SOLDIERTYPE *pSoldier );
void SetEngagedInConvFromPCAction( SOLDIERTYPE *pSoldier );
extern UINT32 guiDialogueLastQuoteTime;
extern UINT32 guiDialogueLastQuoteDelay;
void SetStopTimeQuoteCallback( MODAL_HOOK pCallBack );
BOOLEAN DialogueActive( );
extern INT32 giNPCReferenceCount;
extern INT32 giNPCSpecialReferenceCount;
#define NUMBER_VALID_MERC_PRECEDENT_QUOTES 13
extern UINT8 gubMercValidPrecedentQuoteID[ NUMBER_VALID_MERC_PRECEDENT_QUOTES ];
BOOLEAN ShouldMercSayPrecedentToRepeatOneSelf( UINT8 ubMercID, UINT32 uiQuoteID );
BOOLEAN GetMercPrecedentQuoteBitStatus( UINT8 ubMercID, UINT8 ubQuoteBit );
BOOLEAN SetMercPrecedentQuoteBitStatus( UINT8 ubMercID, UINT8 ubBitToSet );
BOOLEAN IsQuoteInPrecedentArray( UINT32 uiQuoteID );
UINT8 GetQuoteBitNumberFromQuoteID( UINT32 uiQuoteID );
void HandleShutDownOfMapScreenWhileExternfaceIsTalking( void );
void StopAnyCurrentlyTalkingSpeech( );
// handle pausing of the dialogue queue
void PauseDialogueQueue( void );
// unpause the dialogue queue
void UnPauseDialogueQueue( void );
void SetExternMapscreenSpeechPanelXY( INT16 sXPos, INT16 sYPos );
#endif
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
#ifndef _DISPLAY_COVER__H_
#define _DISPLAY_COVER__H_
void DisplayCoverOfSelectedGridNo( );
void RemoveCoverOfSelectedGridNo();
void DisplayRangeToTarget( SOLDIERTYPE *pSoldier, INT16 sTargetGridNo );
void RemoveVisibleGridNoAtSelectedGridNo();
void DisplayGridNoVisibleToSoldierGrid( );
#ifdef JA2TESTVERSION
void DisplayLosAndDisplayCoverUsageScreenMsg();
#endif
void ChangeSizeOfDisplayCover( INT32 iNewSize );
void ChangeSizeOfLOS( INT32 iNewSize );
#endif
+459
View File
@@ -0,0 +1,459 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "sgp.h"
#include "soldier control.h"
#include "soldier profile.h"
#include "drugs and alcohol.h"
#include "items.h"
#include "drugs and alcohol.h"
#include "morale.h"
#include "points.h"
#include "message.h"
#endif
UINT8 ubDrugTravelRate[] = { 4, 2 };
UINT8 ubDrugWearoffRate[] = { 2, 2 };
UINT8 ubDrugEffect[] = { 15, 8 };
UINT8 ubDrugSideEffect[] = { 20, 10 };
UINT8 ubDrugSideEffectRate[] = { 2, 1 };
INT32 giDrunkModifier[] =
{
100, // Sober
75, // Feeling good,
65, // Bporderline
50, // Drunk
100, // HungOver
};
#define HANGOVER_AP_REDUCE 5
#define HANGOVER_BP_REDUCE 200
UINT8 GetDrugType( UINT16 usItem )
{
if ( usItem == ADRENALINE_BOOSTER )
{
return( DRUG_TYPE_ADRENALINE );
}
if ( usItem == REGEN_BOOSTER )
{
return( DRUG_TYPE_REGENERATION );
}
if ( usItem == ALCOHOL || usItem == WINE || usItem == BEER )
{
return( DRUG_TYPE_ALCOHOL );
}
return( NO_DRUG );
}
BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject )
{
UINT8 ubDrugType;
UINT8 ubKitPoints;
INT8 bRegenPointsGained;
UINT16 usItem;
usItem = pObject->usItem;
// If not a syringe, return
ubDrugType = GetDrugType( usItem );
// Determine what type of drug....
if ( ubDrugType == NO_DRUG )
{
return( FALSE );
}
// do switch for Larry!!
if ( pSoldier->ubProfile == LARRY_NORMAL )
{
pSoldier = SwapLarrysProfiles( pSoldier );
}
else if ( pSoldier->ubProfile == LARRY_DRUNK )
{
gMercProfiles[ LARRY_DRUNK ].bNPCData = 0;
}
if ( ubDrugType < NUM_COMPLEX_DRUGS )
{
// Add effects
if ( ( pSoldier->bFutureDrugEffect[ ubDrugType ] + ubDrugEffect[ ubDrugType ] ) < 127 )
{
pSoldier->bFutureDrugEffect[ ubDrugType ] += ubDrugEffect[ ubDrugType ];
}
pSoldier->bDrugEffectRate[ ubDrugType ] = ubDrugTravelRate[ ubDrugType ];
// Increment times used during lifetime...
// CAP!
if ( ubDrugType == DRUG_TYPE_ADRENALINE )
{
if ( gMercProfiles[ pSoldier->ubProfile ].ubNumTimesDrugUseInLifetime != 255 )
{
gMercProfiles[ pSoldier->ubProfile ].ubNumTimesDrugUseInLifetime++;
}
}
// Reset once we sleep...
pSoldier->bTimesDrugUsedSinceSleep[ ubDrugType ]++;
// Increment side effects..
if ( ( pSoldier->bDrugSideEffect[ ubDrugType ] + ubDrugSideEffect[ ubDrugType ] ) < 127 )
{
pSoldier->bDrugSideEffect[ ubDrugType ] += ( ubDrugSideEffect[ ubDrugType ] );
}
// Stop side effects until were done....
pSoldier->bDrugSideEffectRate[ ubDrugType ] = 0;
if ( ubDrugType == DRUG_TYPE_ALCOHOL )
{
// ATE: use kit points...
if ( usItem == ALCOHOL )
{
ubKitPoints = 10;
}
else if ( usItem == WINE )
{
ubKitPoints = 20;
}
else
{
ubKitPoints = 100;
}
UseKitPoints( pObject, ubKitPoints, pSoldier );
}
else
{
// Remove the object....
DeleteObj( pObject );
// ATE: Make guy collapse from heart attack if too much stuff taken....
if ( pSoldier->bDrugSideEffectRate[ ubDrugType ] > ( ubDrugSideEffect[ ubDrugType ] * 3 ) )
{
// Keel over...
DeductPoints( pSoldier, 0, 10000 );
// Permanently lower certain stats...
pSoldier->bWisdom -= 5;
pSoldier->bDexterity -= 5;
pSoldier->bStrength -= 5;
if (pSoldier->bWisdom < 1)
pSoldier->bWisdom = 1;
if (pSoldier->bDexterity < 1)
pSoldier->bDexterity = 1;
if (pSoldier->bStrength < 1)
pSoldier->bStrength = 1;
// export stat changes to profile
gMercProfiles[ pSoldier->ubProfile ].bWisdom = pSoldier->bWisdom;
gMercProfiles[ pSoldier->ubProfile ].bDexterity = pSoldier->bDexterity;
gMercProfiles[ pSoldier->ubProfile ].bStrength = pSoldier->bStrength;
// make those stats RED for a while...
pSoldier->uiChangeWisdomTime = GetJA2Clock();
pSoldier->usValueGoneUp &= ~( WIS_INCREASE );
pSoldier->uiChangeDexterityTime = GetJA2Clock();
pSoldier->usValueGoneUp &= ~( DEX_INCREASE );
pSoldier->uiChangeStrengthTime = GetJA2Clock();
pSoldier->usValueGoneUp &= ~( STRENGTH_INCREASE );
}
}
}
else
{
if ( ubDrugType == DRUG_TYPE_REGENERATION )
{
// each use of a regen booster over 1, each day, reduces the effect
bRegenPointsGained = REGEN_POINTS_PER_BOOSTER * pObject->bStatus[0] / 100;
// are there fractional %s left over?
if ( ( pObject->bStatus[0] % (100 / REGEN_POINTS_PER_BOOSTER ) ) != 0 )
{
// chance of an extra point
if ( PreRandom( 100 / REGEN_POINTS_PER_BOOSTER ) < (UINT32) ( pObject->bStatus[0] % (100 / REGEN_POINTS_PER_BOOSTER ) ) )
{
bRegenPointsGained++;
}
}
bRegenPointsGained -= pSoldier->bRegenBoostersUsedToday;
if (bRegenPointsGained > 0)
{
// can't go above the points you get for a full boost
pSoldier->bRegenerationCounter = __min( pSoldier->bRegenerationCounter + bRegenPointsGained, REGEN_POINTS_PER_BOOSTER );
}
pSoldier->bRegenBoostersUsedToday++;
}
// remove object
DeleteObj( pObject );
}
if ( ubDrugType == DRUG_TYPE_ALCOHOL )
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_DRANK_SOME ], pSoldier->name, ShortItemNames[ usItem ] );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, pMessageStrings[ MSG_MERC_TOOK_DRUG ], pSoldier->name );
}
// Dirty panel
fInterfacePanelDirty = DIRTYLEVEL2;
return( TRUE );
}
void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier )
{
INT32 cnt, cnt2;
INT32 iNumLoops;
// INT8 bBandaged;
for ( cnt = 0; cnt < NUM_COMPLEX_DRUGS; cnt++ )
{
// If side effect aret is non-zero....
if ( pSoldier->bDrugSideEffectRate[ cnt ] > 0 )
{
// Subtract some...
pSoldier->bDrugSideEffect[ cnt ] -= pSoldier->bDrugSideEffectRate[ cnt ];
// If we're done, we're done!
if ( pSoldier->bDrugSideEffect[ cnt ] <= 0 )
{
pSoldier->bDrugSideEffect[ cnt ] = 0;
fInterfacePanelDirty = DIRTYLEVEL1;
}
}
// IF drug rate is -ve, it's being worn off...
if ( pSoldier->bDrugEffectRate[ cnt ] < 0 )
{
pSoldier->bDrugEffect[ cnt ] -= ( -1 * pSoldier->bDrugEffectRate[ cnt ] );
// Have we run out?
if ( pSoldier->bDrugEffect[ cnt ] <= 0 )
{
pSoldier->bDrugEffect[ cnt ] = 0;
// Dirty panel
fInterfacePanelDirty = DIRTYLEVEL2;
// Start the bad news!
pSoldier->bDrugSideEffectRate[ cnt ] = ubDrugSideEffectRate[ cnt ];
// The drug rate is 0 now too
pSoldier->bDrugEffectRate[ cnt ] = 0;
// Once for each 'level' of crash....
iNumLoops = ( pSoldier->bDrugSideEffect[ cnt ] / ubDrugSideEffect[ cnt ] ) + 1;
for ( cnt2 = 0; cnt2 < iNumLoops; cnt2++ )
{
// OK, give a much BIGGER morale downer
if ( cnt == DRUG_TYPE_ALCOHOL )
{
HandleMoraleEvent( pSoldier, MORALE_ALCOHOL_CRASH, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
else
{
HandleMoraleEvent( pSoldier, MORALE_DRUGS_CRASH, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
}
}
}
// Add increase ineffect....
if ( pSoldier->bDrugEffectRate[ cnt ] > 0 )
{
// Seap some in....
pSoldier->bFutureDrugEffect[ cnt ] -= pSoldier->bDrugEffectRate[ cnt ];
pSoldier->bDrugEffect[ cnt ] += pSoldier->bDrugEffectRate[ cnt ];
// Refresh morale w/ new drug value...
RefreshSoldierMorale( pSoldier );
// Check if we need to stop 'adding'
if ( pSoldier->bFutureDrugEffect[ cnt ] <= 0 )
{
pSoldier->bFutureDrugEffect[ cnt ] = 0;
// Change rate to -ve..
pSoldier->bDrugEffectRate[ cnt ] = -ubDrugWearoffRate[ cnt ];
}
}
}
if ( pSoldier->bRegenerationCounter > 0)
{
// bBandaged = BANDAGED( pSoldier );
// increase life
pSoldier->bLife = __min( pSoldier->bLife + LIFE_GAIN_PER_REGEN_POINT, pSoldier->bLifeMax );
if ( pSoldier->bLife == pSoldier->bLifeMax )
{
pSoldier->bBleeding = 0;
}
else if ( pSoldier->bBleeding + pSoldier->bLife > pSoldier->bLifeMax )
{
// got to reduce amount of bleeding
pSoldier->bBleeding = (pSoldier->bLifeMax - pSoldier->bLife);
}
// decrement counter
pSoldier->bRegenerationCounter--;
}
}
INT8 GetDrugEffect( SOLDIERTYPE *pSoldier, UINT8 ubDrugType )
{
return( pSoldier->bDrugEffect[ ubDrugType ] );
}
INT8 GetDrugSideEffect( SOLDIERTYPE *pSoldier, UINT8 ubDrugType )
{
// If we have a o-positive effect
if ( pSoldier->bDrugEffect[ ubDrugType ] > 0 )
{
return( 0 );
}
else
{
return( pSoldier->bDrugSideEffect[ ubDrugType ] );
}
}
void HandleAPEffectDueToDrugs( SOLDIERTYPE *pSoldier, UINT8 *pubPoints )
{
INT8 bDrunkLevel;
INT16 sPoints = (*pubPoints);
// Are we in a side effect or good effect?
if ( pSoldier->bDrugEffect[ DRUG_TYPE_ADRENALINE ] )
{
// Adjust!
sPoints += pSoldier->bDrugEffect[ DRUG_TYPE_ADRENALINE ];
}
else if ( pSoldier->bDrugSideEffect[ DRUG_TYPE_ADRENALINE ] )
{
// Adjust!
sPoints -= pSoldier->bDrugSideEffect[ DRUG_TYPE_ADRENALINE ];
if ( sPoints < AP_MINIMUM )
{
sPoints = AP_MINIMUM;
}
}
bDrunkLevel = GetDrunkLevel( pSoldier );
if ( bDrunkLevel == HUNGOVER )
{
// Reduce....
sPoints -= HANGOVER_AP_REDUCE;
if ( sPoints < AP_MINIMUM )
{
sPoints = AP_MINIMUM;
}
}
(*pubPoints) = (UINT8)sPoints;
}
void HandleBPEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT16 *psPointReduction )
{
INT8 bDrunkLevel;
// Are we in a side effect or good effect?
if ( pSoldier->bDrugEffect[ DRUG_TYPE_ADRENALINE ] )
{
// Adjust!
(*psPointReduction) -= ( pSoldier->bDrugEffect[ DRUG_TYPE_ADRENALINE ] * BP_RATIO_RED_PTS_TO_NORMAL );
}
else if ( pSoldier->bDrugSideEffect[ DRUG_TYPE_ADRENALINE ] )
{
// Adjust!
(*psPointReduction) += ( pSoldier->bDrugSideEffect[ DRUG_TYPE_ADRENALINE ] * BP_RATIO_RED_PTS_TO_NORMAL );
}
bDrunkLevel = GetDrunkLevel( pSoldier );
if ( bDrunkLevel == HUNGOVER )
{
// Reduce....
(*psPointReduction) += HANGOVER_BP_REDUCE;
}
}
INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier )
{
INT8 bNumDrinks;
// If we have a -ve effect ...
if ( pSoldier->bDrugEffect[ DRUG_TYPE_ALCOHOL ] == 0 && pSoldier->bDrugSideEffect[ DRUG_TYPE_ALCOHOL ] == 0 )
{
return( SOBER );
}
if ( pSoldier->bDrugEffect[ DRUG_TYPE_ALCOHOL ] == 0 && pSoldier->bDrugSideEffect[ DRUG_TYPE_ALCOHOL ] != 0 )
{
return( HUNGOVER );
}
// Calculate how many dinks we have had....
bNumDrinks = ( pSoldier->bDrugEffect[ DRUG_TYPE_ALCOHOL ] / ubDrugEffect[ DRUG_TYPE_ALCOHOL ] );
if ( bNumDrinks <= 3 )
{
return( FEELING_GOOD );
}
else if ( bNumDrinks <= 4 )
{
return( BORDERLINE );
}
else
{
return( DRUNK );
}
}
INT32 EffectStatForBeingDrunk( SOLDIERTYPE *pSoldier, INT32 iStat )
{
return( ( iStat * giDrunkModifier[ GetDrunkLevel( pSoldier ) ] / 100 ) );
}
BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier )
{
// Are we in a side effect or good effect?
if ( pSoldier->bDrugEffect[ DRUG_TYPE_ADRENALINE ] )
{
return( TRUE );
}
else if ( pSoldier->bDrugSideEffect[ DRUG_TYPE_ADRENALINE ] )
{
return( TRUE );
}
if ( GetDrunkLevel( pSoldier ) != SOBER )
{
return( TRUE );
}
return( FALSE );
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef __DRUGS_AND_ALCOHOL_H
#define __DRUGS_AND_ALCOHOL_H
#define DRUG_TYPE_ADRENALINE 0
#define DRUG_TYPE_ALCOHOL 1
#define NO_DRUG 2
#define NUM_COMPLEX_DRUGS 2
#define DRUG_TYPE_REGENERATION 3
#define SOBER 0
#define FEELING_GOOD 1
#define BORDERLINE 2
#define DRUNK 3
#define HUNGOVER 4
#define REGEN_POINTS_PER_BOOSTER 4
#define LIFE_GAIN_PER_REGEN_POINT 10
UINT8 GetDrugType( UINT16 usItem );
BOOLEAN ApplyDrugs( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject );
void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier );
void HandleAPEffectDueToDrugs( SOLDIERTYPE *pSoldier, UINT8 *pubPoints );
void HandleBPEffectDueToDrugs( SOLDIERTYPE *pSoldier, INT16 *psPoints );
INT8 GetDrugEffect( SOLDIERTYPE *pSoldier, UINT8 ubDrugType );
INT8 GetDrugSideEffect( SOLDIERTYPE *pSoldier, UINT8 ubDrugType );
INT8 GetDrunkLevel( SOLDIERTYPE *pSoldier );
INT32 EffectStatForBeingDrunk( SOLDIERTYPE *pSoldier, INT32 iStat );
BOOLEAN MercUnderTheInfluence( SOLDIERTYPE *pSoldier );
#endif
+482
View File
@@ -0,0 +1,482 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "PreBattle Interface.h"
#include "Intro.h"
#else
#include "Soldier Control.h"
#include "Overhead.h"
#include "Boxing.h"
#include "Render Fun.h"
#include "Random.h"
#include "Worldman.h"
#include "Soldier Profile.h"
#include "NPC.h"
#include "Opplist.h"
#include "ai.h"
#include "Dialogue Control.h"
#include "Handle UI.h"
#include "Points.h"
#include "interface.h"
#include "end game.h"
#include "Intro.h"
#endif
INT16 sStatueGridNos[] = { 13829, 13830, 13669, 13670 };
SOLDIERTYPE *gpKillerSoldier = NULL;
INT16 gsGridNo;
INT8 gbLevel;
// This function checks if our statue exists in the current sector at given gridno
BOOLEAN DoesO3SectorStatueExistHere( INT16 sGridNo )
{
INT32 cnt;
EXITGRID ExitGrid;
// First check current sector......
if ( gWorldSectorX == 3 && gWorldSectorY == MAP_ROW_O && gbWorldSectorZ == 0 )
{
// Check for exitence of and exit grid here...
// ( if it doesn't then the change has already taken place )
if ( !GetExitGrid( 13669, &ExitGrid ) )
{
for ( cnt = 0; cnt < 4; cnt++ )
{
if ( sStatueGridNos[ cnt ] == sGridNo )
{
return( TRUE );
}
}
}
}
return( FALSE );
}
// This function changes the graphic of the statue and adds the exit grid...
void ChangeO3SectorStatue( BOOLEAN fFromExplosion )
{
EXITGRID ExitGrid;
UINT16 usTileIndex;
INT16 sX, sY;
// Remove old graphic
ApplyMapChangesToMapTempFile( TRUE );
// Remove it!
// Get index for it...
GetTileIndexFromTypeSubIndex( EIGHTOSTRUCT, (INT8)( 5 ), &usTileIndex );
RemoveStruct( 13830, usTileIndex );
// Add new one...
if ( fFromExplosion )
{
// Use damaged peice
GetTileIndexFromTypeSubIndex( EIGHTOSTRUCT, (INT8)( 7 ), &usTileIndex );
}
else
{
GetTileIndexFromTypeSubIndex( EIGHTOSTRUCT, (INT8)( 8 ), &usTileIndex );
// Play sound...
PlayJA2Sample( OPEN_STATUE, RATE_11025, HIGHVOLUME, 1, MIDDLEPAN );
}
AddStructToHead( 13830, usTileIndex );
// Add exit grid
ExitGrid.ubGotoSectorX = 3;
ExitGrid.ubGotoSectorY = MAP_ROW_O;
ExitGrid.ubGotoSectorZ = 1;
ExitGrid.usGridNo = 13037;
AddExitGridToWorld( 13669, &ExitGrid );
gpWorldLevelData[ 13669 ].uiFlags |= MAPELEMENT_REVEALED;
// Turn off permenant changes....
ApplyMapChangesToMapTempFile( FALSE );
// Re-render the world!
gTacticalStatus.uiFlags |= NOHIDE_REDUNDENCY;
// FOR THE NEXT RENDER LOOP, RE-EVALUATE REDUNDENT TILES
InvalidateWorldRedundency( );
SetRenderFlags(RENDER_FLAG_FULL);
// Redo movement costs....
ConvertGridNoToXY( 13830, &sX, &sY );
RecompileLocalMovementCostsFromRadius( 13830, 5 );
}
void DeidrannaTimerCallback( void )
{
HandleDeidrannaDeath( gpKillerSoldier, gsGridNo, gbLevel );
}
void BeginHandleDeidrannaDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel )
{
gpKillerSoldier = pKillerSoldier;
gsGridNo = sGridNo;
gbLevel = bLevel;
// Lock the UI.....
gTacticalStatus.uiFlags |= ENGAGED_IN_CONV;
// Increment refrence count...
giNPCReferenceCount = 1;
gTacticalStatus.uiFlags |= IN_DEIDRANNA_ENDGAME;
SetCustomizableTimerCallbackAndDelay( 2000, DeidrannaTimerCallback, FALSE );
}
void HandleDeidrannaDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt;
INT16 sDistVisible = FALSE;
UINT8 ubKillerSoldierID = NOBODY;
// Start victory music here...
SetMusicMode( MUSIC_TACTICAL_VICTORY );
if ( pKillerSoldier )
{
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLING_DEIDRANNA );
ubKillerSoldierID = pKillerSoldier->ubID;
}
// STEP 1 ) START ALL QUOTES GOING!
// OK - loop through all witnesses and see if they want to say something abou this...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
{
if ( cnt != ubKillerSoldierID )
{
if ( OK_INSECTOR_MERC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !AM_AN_EPC( pTeamSoldier ) )
{
if ( QuoteExp_WitnessDeidrannaDeath[ pTeamSoldier->ubProfile ] )
{
// Can we see location?
sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel );
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, (UINT8) sDistVisible, TRUE ) )
{
TacticalCharacterDialogue( pTeamSoldier, QUOTE_KILLING_DEIDRANNA );
}
}
}
}
}
// Set fact that she is dead!
SetFactTrue( FACT_QUEEN_DEAD );
ExecuteStrategicAIAction( STRATEGIC_AI_ACTION_QUEEN_DEAD, 0, 0 );
// AFTER LAST ONE IS DONE - PUT SPECIAL EVENT ON QUEUE TO BEGIN FADE< ETC
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE, MULTIPURPOSE_SPECIAL_EVENT_DONE_KILLING_DEIDRANNA, 0,0,0,0 );
}
void DoneFadeInKilledQueen( void )
{
SOLDIERTYPE *pNPCSoldier;
// Locate gridno.....
// Run NPC script
pNPCSoldier = FindSoldierByProfileID( 136, FALSE );
if ( !pNPCSoldier )
{
return;
}
// Converse!
//InitiateConversation( pNPCSoldier, pSoldier, 0, 1 );
TriggerNPCRecordImmediately( pNPCSoldier->ubProfile, 6 );
}
void DoneFadeOutKilledQueen( void )
{
INT32 cnt;
SOLDIERTYPE *pSoldier, *pTeamSoldier;
// For one, loop through our current squad and move them over
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// look for all mercs on the same team,
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
{
// Are we in this sector, On the current squad?
if ( pSoldier->bActive && pSoldier->bLife >= OKLIFE && pSoldier->bInSector && pSoldier->bAssignment == CurrentSquad( ) )
{
gfTacticalTraversal = TRUE;
SetGroupSectorValue( 3, MAP_ROW_P, 0, pSoldier->ubGroupID );
// Set next sectore
pSoldier->sSectorX = 3;
pSoldier->sSectorY = MAP_ROW_P;
pSoldier->bSectorZ = 0;
// Set gridno
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_GRIDNO;
pSoldier->usStrategicInsertionData = 5687;
// Set direction to face....
pSoldier->ubInsertionDirection = 100 + NORTHWEST;
}
}
// Kill all enemies in world.....
cnt = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
// look for all mercs on the same team,
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ ENEMY_TEAM ].bLastID; cnt++,pTeamSoldier++)
{
// Are we active and in sector.....
if ( pTeamSoldier->bActive )
{
// For sure for flag thet they are dead is not set
// Check for any more badguys
// ON THE STRAGETY LAYER KILL BAD GUYS!
if ( !pTeamSoldier->bNeutral && (pTeamSoldier->bSide != gbPlayerNum ) )
{
ProcessQueenCmdImplicationsOfDeath( pSoldier );
}
}
}
// 'End' battle
ExitCombatMode();
gTacticalStatus.fLastBattleWon = TRUE;
// Set enemy presence to false
gTacticalStatus.fEnemyInSector = FALSE;
SetMusicMode( MUSIC_TACTICAL_VICTORY );
HandleMoraleEvent( NULL, MORALE_QUEEN_BATTLE_WON, 3, MAP_ROW_P, 0 );
HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_QUEEN_BATTLE_WON, 3, MAP_ROW_P, 0 );
SetMusicMode( MUSIC_TACTICAL_VICTORY );
SetThisSectorAsPlayerControlled( gWorldSectorX, gWorldSectorY, gbWorldSectorZ, TRUE );
// ATE: Force change of level set z to 1
gbWorldSectorZ = 1;
// Clear out dudes.......
SectorInfo[ SEC_P3 ].ubNumAdmins = 0;
SectorInfo[ SEC_P3 ].ubNumTroops = 0;
SectorInfo[ SEC_P3 ].ubNumElites = 0;
SectorInfo[ SEC_P3 ].ubAdminsInBattle = 0;
SectorInfo[ SEC_P3 ].ubTroopsInBattle = 0;
SectorInfo[ SEC_P3 ].ubElitesInBattle = 0;
// ATE: GEt rid of elliot in P3...
gMercProfiles[ ELLIOT ].sSectorX = 1;
ChangeNpcToDifferentSector( DEREK, 3, MAP_ROW_P, 0 );
ChangeNpcToDifferentSector( OLIVER, 3, MAP_ROW_P, 0 );
// OK, insertion data found, enter sector!
SetCurrentWorldSector( 3, MAP_ROW_P, 0 );
// OK, once down here, adjust the above map with crate info....
gfTacticalTraversal = FALSE;
gpTacticalTraversalGroup = NULL;
gpTacticalTraversalChosenSoldier = NULL;
gFadeInDoneCallback = DoneFadeInKilledQueen;
FadeInGameScreen( );
}
// Called after all player quotes are done....
void HandleDoneLastKilledQueenQuote( )
{
gFadeOutDoneCallback = DoneFadeOutKilledQueen;
FadeOutGameScreen( );
}
void EndQueenDeathEndgameBeginEndCimenatic( )
{
INT32 cnt;
SOLDIERTYPE *pSoldier;
// Start end cimimatic....
gTacticalStatus.uiFlags |= IN_ENDGAME_SEQUENCE;
// first thing is to loop through team and say end quote...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// look for all mercs on the same team,
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
{
// Are we in this sector, On the current squad?
if ( pSoldier->bActive && pSoldier->bLife >= OKLIFE && !AM_AN_EPC( pSoldier ) )
{
TacticalCharacterDialogue( pSoldier, QUOTE_END_GAME_COMMENT );
}
}
// Add queue event to proceed w/ smacker cimimatic
SpecialCharacterDialogueEvent( DIALOGUE_SPECIAL_EVENT_MULTIPURPOSE, MULTIPURPOSE_SPECIAL_EVENT_TEAM_MEMBERS_DONE_TALKING, 0,0,0,0 );
}
void EndQueenDeathEndgame( )
{
// Unset flags...
gTacticalStatus.uiFlags &= (~ENGAGED_IN_CONV );
// Increment refrence count...
giNPCReferenceCount = 0;
gTacticalStatus.uiFlags &= (~IN_DEIDRANNA_ENDGAME);
}
void DoneFadeOutEndCinematic( void )
{
// DAVE PUT SMAKER STUFF HERE!!!!!!!!!!!!
// :)
gTacticalStatus.uiFlags &= (~IN_ENDGAME_SEQUENCE);
// For now, just quit the freaken game...
// InternalLeaveTacticalScreen( MAINMENU_SCREEN );
InternalLeaveTacticalScreen( INTRO_SCREEN );
// guiCurrentScreen = INTRO_SCREEN;
SetIntroType( INTRO_ENDING );
}
// OK, end death UI - fade to smaker....
void HandleDoneLastEndGameQuote( )
{
EndQueenDeathEndgame( );
gFadeOutDoneCallback = DoneFadeOutEndCinematic;
FadeOutGameScreen( );
}
void QueenBitchTimerCallback( void )
{
HandleQueenBitchDeath( gpKillerSoldier, gsGridNo, gbLevel );
}
void BeginHandleQueenBitchDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt;
gpKillerSoldier = pKillerSoldier;
gsGridNo = sGridNo;
gbLevel = bLevel;
// Lock the UI.....
gTacticalStatus.uiFlags |= ENGAGED_IN_CONV;
// Increment refrence count...
giNPCReferenceCount = 1;
// gTacticalStatus.uiFlags |= IN_DEIDRANNA_ENDGAME;
SetCustomizableTimerCallbackAndDelay( 3000, QueenBitchTimerCallback, FALSE );
// Kill all enemies in creature team.....
cnt = gTacticalStatus.Team[ CREATURE_TEAM ].bFirstID;
// look for all mercs on the same team,
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ CREATURE_TEAM ].bLastID; cnt++,pTeamSoldier++)
{
// Are we active and ALIVE and in sector.....
if ( pTeamSoldier->bActive && pTeamSoldier->bLife > 0 )
{
// For sure for flag thet they are dead is not set
// Check for any more badguys
// ON THE STRAGETY LAYER KILL BAD GUYS!
// HELLO! THESE ARE CREATURES! THEY CAN'T BE NEUTRAL!
//if ( !pTeamSoldier->bNeutral && (pTeamSoldier->bSide != gbPlayerNum ) )
{
gTacticalStatus.ubAttackBusyCount++;
EVENT_SoldierGotHit( pTeamSoldier, 0, 10000, 0, pTeamSoldier->bDirection, 320, NOBODY , FIRE_WEAPON_NO_SPECIAL, pTeamSoldier->bAimShotLocation, 0, NOWHERE );
}
}
}
}
void HandleQueenBitchDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel )
{
SOLDIERTYPE *pTeamSoldier;
INT32 cnt;
INT16 sDistVisible = FALSE;
UINT8 ubKillerSoldierID = NOBODY;
// Start victory music here...
SetMusicMode( MUSIC_TACTICAL_VICTORY );
if ( pKillerSoldier )
{
TacticalCharacterDialogue( pKillerSoldier, QUOTE_KILLING_QUEEN );
ubKillerSoldierID = pKillerSoldier->ubID;
}
// STEP 1 ) START ALL QUOTES GOING!
// OK - loop through all witnesses and see if they want to say something abou this...
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// run through list
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pTeamSoldier++ )
{
if ( cnt != ubKillerSoldierID )
{
if ( OK_INSECTOR_MERC( pTeamSoldier ) && !( pTeamSoldier->uiStatusFlags & SOLDIER_GASSED ) && !AM_AN_EPC( pTeamSoldier ) )
{
if ( QuoteExp_WitnessQueenBugDeath[ pTeamSoldier->ubProfile ] )
{
// Can we see location?
sDistVisible = DistanceVisible( pTeamSoldier, DIRECTION_IRRELEVANT, DIRECTION_IRRELEVANT, sGridNo, bLevel );
if ( SoldierTo3DLocationLineOfSightTest( pTeamSoldier, sGridNo, bLevel, 3, (UINT8) sDistVisible, TRUE ) )
{
TacticalCharacterDialogue( pTeamSoldier, QUOTE_KILLING_QUEEN );
}
}
}
}
}
// Set fact that she is dead!
if ( CheckFact( FACT_QUEEN_DEAD, 0 ) )
{
EndQueenDeathEndgameBeginEndCimenatic( );
}
else
{
// Unset flags...
gTacticalStatus.uiFlags &= (~ENGAGED_IN_CONV );
// Increment refrence count...
giNPCReferenceCount = 0;
}
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef __ENDGAME_H
#define __ENDGAME_H
BOOLEAN DoesO3SectorStatueExistHere( INT16 sGridNo );
void ChangeO3SectorStatue( BOOLEAN fFromExplosion );
void HandleDeidrannaDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel );
void BeginHandleDeidrannaDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel );
void HandleDoneLastKilledQueenQuote( );
void EndQueenDeathEndgameBeginEndCimenatic( );
void EndQueenDeathEndgame( );
void HandleQueenBitchDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel );
void BeginHandleQueenBitchDeath( SOLDIERTYPE *pKillerSoldier, INT16 sGridNo, INT8 bLevel );
void HandleDoneLastEndGameQuote( );
#endif
File diff suppressed because it is too large Load Diff
+25
View File
@@ -0,0 +1,25 @@
#ifndef __ENEMY_SOLDIER_SAVE_H
#define __ENEMY_SOLDIER_SAVE_H
#include "FileMan.h"
//This funciton load both the enemies AND the civilians, now only used to load old saves
BOOLEAN LoadEnemySoldiersFromTempFile();
//The new way of loading in enemies from the temp file. ONLY the ENEMIES are stored in the e_* temp file
BOOLEAN NewWayOfLoadingEnemySoldiersFromTempFile();
//The new way of loading in CIVILIANS from the temp file. ONLY the CIVILIEANS are stored in the c_* temp file
BOOLEAN NewWayOfLoadingCiviliansFromTempFile();
BOOLEAN NewWayOfSavingEnemyAndCivliansToTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, BOOLEAN fEnemy, BOOLEAN fValidateOnly );
BOOLEAN SaveEnemySoldiersToTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ, UINT8 ubFirstIdTeam, UINT8 ubLastIdTeam, BOOLEAN fAppendToFile );
extern BOOLEAN gfRestoringEnemySoldiersFromTempFile;
#endif
+2284
View File
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
#ifndef __GAP_H
#define __GAP_H
#include "faces.h"
typedef UINT8 AudioSample8;
typedef INT16 AudioSample16;
void AudioGapListInit( CHAR8 *zSoundFile, AudioGapList *pGapList );
void AudioGapListDone( AudioGapList *pGapList );
void PollAudioGap( UINT32 uiSampleNum, AudioGapList *pGapList );
UINT32 PlayJA2GapSample( CHAR8 *zSoundFile, UINT32 usRate, UINT32 ubVolume, UINT32 ubLoops, UINT32 uiPan, AudioGapList* pData );
#endif
+273
View File
@@ -0,0 +1,273 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "debug.h"
#include "types.h"
//#include "mssw.h"
#include "gap.h"
#include "Sound Control.h"
#include "soundman.h"
#include "Timer Control.h"
#include <stdio.h>
#include "FileMan.h"
#endif
#if 0
static void AILCALLBACK timer_func( UINT32 user )
{
AudioGapList *pGapList;
pGapList = (AudioGapList*)user;
pGapList->gap_monitor_timer += GAP_TIMER_INTERVAL;
if ( pGapList->audio_gap_active )
{
if ( (pGapList->gap_monitor_timer / 1000) > pGapList->end[ pGapList->gap_monitor_current] )
{
pGapList->audio_gap_active = 0;
pGapList->gap_monitor_current++;
}
}
else
{
if ( pGapList->gap_monitor_current < pGapList->count )
{
if ( ( pGapList->gap_monitor_timer / 1000) >= pGapList->start[ pGapList->gap_monitor_current ])
{
pGapList->audio_gap_active = 1;
}
}
}
}
#endif
void AudioGapListInit( CHAR8 *zSoundFile, AudioGapList *pGapList )
{
// This procedure will load in the appropriate .gap file, corresponding
// to the .wav file in szSoundEffects indexed by uiSampleNum
// The procedure will then allocate and load in the AUDIO_GAP information,
// while counting the number of elements loaded
// FILE *pFile;
HWFILE pFile;
STR pSourceFileName;
STR pDestFileName;
char sFileName[256];
UINT8 counter=0;
AUDIO_GAP *pCurrentGap, *pPreviousGap;
UINT32 Start;
UINT32 uiNumBytesRead;
UINT32 End;
pSourceFileName= zSoundFile;
pDestFileName=sFileName;
//Initialize GapList
pGapList->size=0;
pGapList->current_time=0;
pGapList->pHead=0;
pGapList->pCurrent=0;
pGapList->audio_gap_active=FALSE;
pPreviousGap=pCurrentGap=0;
//DebugMsg(TOPIC_JA2, DBG_LEVEL_3,String("File is %s", szSoundEffects[uiSampleNum]));
// Get filename
strcpy(pDestFileName, pSourceFileName);
// strip .wav and change to .gap
while(pDestFileName[counter] !='.')
{
counter++;
}
pDestFileName[counter+1]='g';
pDestFileName[counter+2]='a';
pDestFileName[counter+3]='p';
pDestFileName[counter+4]='\0';
pFile = FileOpen(pDestFileName, FILE_ACCESS_READ, FALSE );
if( pFile )
{
counter=0;
// gap file exists
// now read in the AUDIO_GAPs
//fread(&Start,sizeof(UINT32), 1, pFile);
FileRead( pFile, &Start,sizeof(UINT32), &uiNumBytesRead );
// while ( !feof(pFile) )
while ( !FileCheckEndOfFile( pFile ) )
{
// can read the first element, there exists a second
//fread(&End, sizeof(UINT32),1,pFile);
FileRead( pFile, &End, sizeof(UINT32), &uiNumBytesRead );
// allocate space for AUDIO_GAP
pCurrentGap = (AUDIO_GAP *)MemAlloc( sizeof(AUDIO_GAP) );
if (pPreviousGap !=0)
pPreviousGap->pNext=pCurrentGap;
else
{
// Start of list
pGapList->pCurrent=pCurrentGap;
pGapList->pHead=pCurrentGap;
}
pGapList->size++;
pCurrentGap->pNext=0;
pCurrentGap->uiStart=Start;
pCurrentGap->uiEnd=End;
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Gap Start %d and Ends %d", Start, End) );
// Increment pointer
pPreviousGap=pCurrentGap;
// fread(&Start,sizeof(UINT32), 1, pFile);
FileRead( pFile, &Start, sizeof(UINT32), &uiNumBytesRead );
}
pGapList->audio_gap_active=FALSE;
pGapList->current_time=0;
//fclose(pFile);
FileClose( pFile );
}
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Gap List Started From File %s and has %d gaps", pDestFileName, pGapList->size) );
}
void AudioGapListDone( AudioGapList *pGapList )
{
// This procedure will go through the AudioGapList and free space/nullify pointers
// for any allocated elements
AUDIO_GAP *pCurrent, *pNext;
if (pGapList->pHead !=0)
{
pCurrent=pGapList->pHead;
pNext=pCurrent->pNext;
// There are elements in the list
while(pNext !=0)
{
// kill pCurrent
MemFree(pCurrent);
pCurrent=pNext;
pNext=pNext->pNext;
}
// now kill the last element
MemFree(pCurrent);
pCurrent=0;
}
pGapList->pHead=0;
pGapList->pCurrent=0;
pGapList->size = 0;
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Audio Gap List Deleted") );
}
void PollAudioGap( UINT32 uiSampleNum, AudioGapList *pGapList )
{
// This procedure will access the AudioGapList pertaining to the .wav about
// to be played and sets the audio_gap_active flag. This is done by
// going to the current AUDIO_GAP element in the AudioGapList, comparing to see if
// the current time is between the uiStart and uiEnd. If so, set flag..if not and
// the uiStart of the next element is not greater than current time, set current to next and repeat
// ...if next elements uiStart is larger than current_time, or no more elements..
// set flag FALSE
UINT32 time;
AUDIO_GAP *pCurrent;
if(!pGapList)
{
// no gap list, return
return;
}
if (pGapList->size > 0)
{
time=SoundGetPosition(uiSampleNum);
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Sound Sample Time is %d", time) );
}
else
{
pGapList->audio_gap_active=(FALSE);
return;
}
// set current ot head of gap list for this sound
pCurrent = pGapList -> pHead;
// check to see if we have fallen behind
if( ( time > pCurrent-> uiEnd ) )
{
// fallen behind
// catchup
while( time > pCurrent -> uiEnd )
{
pCurrent = pCurrent -> pNext;
if( ! pCurrent )
{
pGapList->audio_gap_active=(FALSE);
return;
}
}
}
// check to see if time is within the next AUDIO_GAPs start time
if ( ( time > pCurrent ->uiStart ) && ( time < pCurrent->uiEnd ) )
{
if ((time >pCurrent->uiStart)&&(time < pCurrent->uiEnd))
{
// we are within the time frame
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Gap Started at %d", time) );
pGapList->audio_gap_active=(TRUE);
}
else if ( (time > pCurrent->uiEnd)&&(pGapList->audio_gap_active == TRUE) )
{
// reset if already set
pGapList->audio_gap_active=(FALSE);
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("Gap Ended at %d", time) );
}
}
else
{
pGapList->audio_gap_active=(FALSE);
}
}
UINT32 PlayJA2GapSample( CHAR8 *zSoundFile, UINT32 usRate, UINT32 ubVolume, UINT32 ubLoops, UINT32 uiPan, AudioGapList* pData )
{
SOUNDPARMS spParms;
memset(&spParms, 0xff, sizeof(SOUNDPARMS));
spParms.uiSpeed = usRate;
spParms.uiVolume = (UINT32) ( ( ubVolume / (FLOAT) HIGHVOLUME ) * GetSpeechVolume( ) );
spParms.uiLoop = ubLoops;
spParms.uiPan = uiPan;
spParms.uiPriority=GROUP_PLAYER;
// Setup Gap Detection, if it is not null
if( pData != NULL )
AudioGapListInit( zSoundFile, pData );
return(SoundPlayStreamedFile( zSoundFile, &spParms));
}
File diff suppressed because it is too large Load Diff
+29
View File
@@ -0,0 +1,29 @@
#ifndef _DOORS_H
#define _DOORS_H
#define HANDLE_DOOR_OPEN 1
#define HANDLE_DOOR_EXAMINE 2
#define HANDLE_DOOR_LOCKPICK 3
#define HANDLE_DOOR_FORCE 4
#define HANDLE_DOOR_LOCK 5
#define HANDLE_DOOR_UNLOCK 6
#define HANDLE_DOOR_EXPLODE 7
#define HANDLE_DOOR_UNTRAP 8
#define HANDLE_DOOR_CROWBAR 9
extern BOOLEAN gfSetPerceivedDoorState;
BOOLEAN HandleOpenableStruct( SOLDIERTYPE *pSoldier, INT16 sGridNo, STRUCTURE *pStructure );
void InteractWithOpenableStruct( SOLDIERTYPE *pSoldier, STRUCTURE *pStructure, UINT8 ubDirection, BOOLEAN fDoor );
void InteractWithClosedDoor( SOLDIERTYPE *pSoldier, UINT8 ubHandleCode );
void SetDoorString( INT16 sGridNo );
void HandleDoorChangeFromGridNo( SOLDIERTYPE *pSoldier, INT16 sGridNo, BOOLEAN fNoAnimations );
#endif
File diff suppressed because it is too large Load Diff
+177
View File
@@ -0,0 +1,177 @@
#ifndef __HANDLE_ITEMS_H
#define __HANDLE_ITEMS_H
#include "Soldier Control.h"
#include "World Items.h"
#include "structure.h"
#define ITEM_HANDLE_OK 1
#define ITEM_HANDLE_RELOADING -1
#define ITEM_HANDLE_UNCONSCIOUS -2
#define ITEM_HANDLE_NOAPS -3
#define ITEM_HANDLE_NOAMMO -4
#define ITEM_HANDLE_CANNOT_GETTO_LOCATION -5
#define ITEM_HANDLE_BROKEN -6
#define ITEM_HANDLE_NOROOM -7
#define ITEM_HANDLE_REFUSAL -8
// Define for code to try and pickup all items....
#define ITEM_PICKUP_ACTION_ALL 32000
#define ITEM_PICKUP_SELECTION 31000
#define ITEM_IGNORE_Z_LEVEL -1
#define ITEMLIST_INIT_HANDLE 1
#define ITEMLIST_DISPLAY 2
#define ITEMLIST_HANDLE 3
#define ITEMLIST_END_HANDLE 4
#define ITEMLIST_HANDLE_SELECTION 5
// visibility defines
#define ANY_VISIBILITY_VALUE -10
#define HIDDEN_ITEM -4
#define BURIED -3
#define HIDDEN_IN_OBJECT -2
#define INVISIBLE -1
#define VISIBLE 1
#define ITEM_LOCATOR_DELAY 0x01
#define ITEM_LOCATOR_LOCKED 0x02
// MACRO FOR DEFINING OF ITEM IS VISIBLE
#define ITEMPOOL_VISIBLE( pItemPool ) ( ( pItemPool->bVisible >= 1 ) || (gTacticalStatus.uiFlags&SHOW_ALL_ITEMS) )
typedef void ( *ITEM_POOL_LOCATOR_HOOK )( void );
typedef struct TAG_ITEM_POOL
{
struct TAG_ITEM_POOL *pNext;
struct TAG_ITEM_POOL *pPrev;
INT32 iItemIndex;
INT8 bVisible;
INT8 bFlashColor;
UINT32 uiTimerID;
INT16 sGridNo;
UINT8 ubLevel;
UINT16 usFlags;
INT8 bRenderZHeightAboveLevel;
struct TAG_level_node *pLevelNode;
} ITEM_POOL;
typedef struct
{
ITEM_POOL *pItemPool;
// Additional info for locators
INT8 bRadioFrame;
UINT32 uiLastFrameUpdate;
ITEM_POOL_LOCATOR_HOOK Callback;
BOOLEAN fAllocated;
UINT8 ubFlags;
} ITEM_POOL_LOCATOR;
INT32 HandleItem( SOLDIERTYPE *pSoldier, UINT16 usGridNo, INT8 bLevel, UINT16 usHandItem, BOOLEAN fFromUI );
void SoldierPickupItem( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT16 sGridNo, INT8 bZLevel );
void HandleSoldierPickupItem( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT16 sGridNo, INT8 bZLevel );
void HandleFlashingItems( );
BOOLEAN SoldierDropItem( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj );
void HandleSoldierThrowItem( SOLDIERTYPE *pSoldier, INT16 sGridNo );
BOOLEAN VerifyGiveItem( SOLDIERTYPE *pSoldier, SOLDIERTYPE **ppTargetSoldier );
void SoldierGiveItemFromAnimation( SOLDIERTYPE *pSoldier );
void SoldierGiveItem( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, OBJECTTYPE *pObject, INT8 bInvPos );
void NotifySoldiersToLookforItems( );
void AllSoldiersLookforItems( BOOLEAN RevealRoofsAndItems );
void SoldierGetItemFromWorld( SOLDIERTYPE *pSoldier, INT32 iItemIndex, INT16 sGridNo, INT8 bZLevel, BOOLEAN *pfSelectionList );
OBJECTTYPE* AddItemToPool( INT16 sGridNo, OBJECTTYPE *pObject, INT8 bVisible, UINT8 ubLevel, UINT16 usFlags, INT8 bRenderZHeightAboveLevel );
OBJECTTYPE* AddItemToPoolAndGetIndex( INT16 sGridNo, OBJECTTYPE *pObject, INT8 bVisible, UINT8 ubLevel, UINT16 usFlags, INT8 bRenderZHeightAboveLevel, INT32 * piItemIndex );
OBJECTTYPE* InternalAddItemToPool( INT16 *psGridNo, OBJECTTYPE *pObject, INT8 bVisible, UINT8 ubLevel, UINT16 usFlags, INT8 bRenderZHeightAboveLevel, INT32 * piItemIndex );
INT16 AdjustGridNoForItemPlacement( SOLDIERTYPE *pSoldier, INT16 sGridNo );
BOOLEAN GetItemPool( UINT16 usMapPos, ITEM_POOL **ppItemPool, UINT8 ubLevel );
BOOLEAN DrawItemPoolList( ITEM_POOL *pItemPool, INT16 sGridNo, UINT8 bCommand, INT8 bZLevel, INT16 sXPos, INT16 sYPos );
BOOLEAN RemoveItemFromPool( INT16 sGridNo, INT32 iItemIndex, UINT8 ubLevel );
BOOLEAN ItemExistsAtLocation( INT16 sGridNo, INT32 iItemIndex, UINT8 ubLevel );
BOOLEAN MoveItemPools( INT16 sStartPos, INT16 sEndPos );
void SetItemPoolLocator( ITEM_POOL *pItemPool );
void SetItemPoolLocatorWithCallback( ITEM_POOL *pItemPool, ITEM_POOL_LOCATOR_HOOK Callback );
BOOLEAN SetItemPoolVisibilityOn( ITEM_POOL *pItemPool, INT8 bAllGreaterThan, BOOLEAN fSetLocator );
void AdjustItemPoolVisibility( ITEM_POOL *pItemPool );
void SetItemPoolVisibilityHiddenInObject( ITEM_POOL *pItemPool );
void SetItemPoolVisibilityHidden( ITEM_POOL *pItemPool );
INT32 GetItemOfClassTypeInPool( INT16 sGridNo, UINT32 uiItemClass, UINT8 ubLevel );
void RemoveItemPool( INT16 sGridNo, UINT8 ubLevel );
void RenderTopmostFlashingItems( );
void RemoveAllUnburiedItems( INT16 sGridNo, UINT8 ubLevel );
BOOLEAN DoesItemPoolContainAnyHiddenItems( ITEM_POOL *pItemPool );
BOOLEAN DoesItemPoolContainAllHiddenItems( ITEM_POOL *pItemPool );
void HandleSoldierDropBomb( SOLDIERTYPE *pSoldier, INT16 sGridNo );
void HandleSoldierUseRemote( SOLDIERTYPE *pSoldier, INT16 sGridNo );
BOOLEAN DoesItemPoolContainAllItemsOfZeroZLevel( ITEM_POOL *pItemPool );
BOOLEAN DoesItemPoolContainAllItemsOfHigherZLevel( ITEM_POOL *pItemPool );
BOOLEAN ItemPoolOKForDisplay( ITEM_POOL *pItemPool, INT8 bZLevel );
INT16 GetNumOkForDisplayItemsInPool( ITEM_POOL *pItemPool, INT8 bZLevel );
void SoldierHandleDropItem( SOLDIERTYPE *pSoldier );
BOOLEAN LookForHiddenItems( INT16 sGridNo, INT8 ubLevel, BOOLEAN fSetLocator, INT8 bZLevel );
INT8 GetZLevelOfItemPoolGivenStructure( INT16 sGridNo, UINT8 ubLevel, STRUCTURE *pStructure );
INT8 GetLargestZLevelOfItemPool( ITEM_POOL *pItemPool );
BOOLEAN NearbyGroundSeemsWrong( SOLDIERTYPE * pSoldier, INT16 sGridNo, BOOLEAN fCheckAroundGridno, INT16 * psProblemGridNo );
void MineSpottedDialogueCallBack( void );
extern INT16 gsBoobyTrapGridNo;
extern SOLDIERTYPE * gpBoobyTrapSoldier;
void AddBlueFlag( INT16 sGridNo, INT8 bLevel );
void RemoveBlueFlag( INT16 sGridNo, INT8 bLevel );
// check if item is booby trapped
BOOLEAN ContinuePastBoobyTrapInMapScreen( OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier );
// set off the booby trap in mapscreen
void SetOffBoobyTrapInMapScreen( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject );
void RefreshItemPools( WORLDITEM* pItemList, INT32 iNumberOfItems );
BOOLEAN HandItemWorks( SOLDIERTYPE *pSoldier, INT8 bSlot );
BOOLEAN ItemTypeExistsAtLocation( INT16 sGridNo, UINT16 usItem, UINT8 ubLevel, INT32 * piItemIndex );
INT16 FindNearestAvailableGridNoForItem( INT16 sSweetGridNo, INT8 ubRadius );
BOOLEAN CanPlayerUseRocketRifle( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay );
void MakeNPCGrumpyForMinorOffense( SOLDIERTYPE * pSoldier, SOLDIERTYPE *pOffendingSoldier );
void SoldierStealItemFromSoldier( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent,ITEM_POOL *pItemPool, INT32 iItemIndex, INT16 sGridNo, INT8 bZLevel, BOOLEAN *pfSelectionList );
UINT8 StealItems(SOLDIERTYPE* pSoldier,SOLDIERTYPE* pOpponent, UINT8* ubIndexRet);
BOOLEAN MarblesExistAtLocation( INT16 sGridNo, UINT8 ubLevel, INT32 * piItemIndex );
#endif
+308
View File
@@ -0,0 +1,308 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "Handle UI Plan.h"
#include "overhead.h"
#include "Isometric Utils.h"
#include "pathai.h"
#include "Handle UI.h"
#include "points.h"
#include "weapons.h"
#include "renderworld.h"
#include "Animation Control.h"
#include "message.h"
#include "soldier create.h"
#include "interface.h"
#endif
UINT8 gubNumUIPlannedMoves = 0;
SOLDIERTYPE *gpUIPlannedSoldier = NULL;
SOLDIERTYPE *gpUIStartPlannedSoldier = NULL;
BOOLEAN gfInUIPlanMode = FALSE;
void SelectPausedFireAnimation( SOLDIERTYPE *pSoldier );
BOOLEAN BeginUIPlan( SOLDIERTYPE *pSoldier )
{
gubNumUIPlannedMoves = 0;
gpUIPlannedSoldier = pSoldier;
gpUIStartPlannedSoldier = pSoldier;
gfInUIPlanMode = TRUE;
gfPlotNewMovement = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Entering Planning Mode" );
return( TRUE );
}
BOOLEAN AddUIPlan( UINT16 sGridNo, UINT8 ubPlanID )
{
SOLDIERTYPE *pPlanSoldier;
INT16 sXPos, sYPos;
INT16 sAPCost = 0;
INT8 bDirection;
INT32 iLoop;
SOLDIERCREATE_STRUCT MercCreateStruct;
UINT8 ubNewIndex;
// Depeding on stance and direction facing, add guy!
// If we have a planned action here, ignore!
// If not OK Dest, ignore!
if ( !NewOKDestination( gpUIPlannedSoldier, sGridNo, FALSE, (INT8)gsInterfaceLevel ) )
{
return( FALSE );
}
if ( ubPlanID == UIPLAN_ACTION_MOVETO )
{
// Calculate cost to move here
sAPCost = PlotPath( gpUIPlannedSoldier, sGridNo, COPYROUTE, NO_PLOT, TEMPORARY, (UINT16) gpUIPlannedSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, gpUIPlannedSoldier->bActionPoints );
// Adjust for running if we are not already running
if ( gpUIPlannedSoldier->usUIMovementMode == RUNNING )
{
sAPCost += AP_START_RUN_COST;
}
if ( EnoughPoints( gpUIPlannedSoldier, sAPCost, 0, FALSE ) )
{
memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
MercCreateStruct.bTeam = SOLDIER_CREATE_AUTO_TEAM;
MercCreateStruct.ubProfile = NO_PROFILE;
MercCreateStruct.fPlayerPlan = TRUE;
MercCreateStruct.bBodyType = gpUIPlannedSoldier->ubBodyType;
MercCreateStruct.sInsertionGridNo = sGridNo;
// Get Grid Corrdinates of mouse
if ( TacticalCreateSoldier( &MercCreateStruct, &ubNewIndex ) )
{
// Get pointer to soldier
GetSoldier( &pPlanSoldier, (UINT16)ubNewIndex );
pPlanSoldier->sPlannedTargetX = -1;
pPlanSoldier->sPlannedTargetY = -1;
// Compare OPPLISTS!
// Set ones we don't know about but do now back to old ( ie no new guys )
for (iLoop = 0; iLoop < MAX_NUM_SOLDIERS; iLoop++ )
{
if ( gpUIPlannedSoldier->bOppList[ iLoop ] < 0 )
{
pPlanSoldier->bOppList[ iLoop ] = gpUIPlannedSoldier->bOppList[ iLoop ];
}
}
// Get XY from Gridno
ConvertGridNoToCenterCellXY( sGridNo, &sXPos, &sYPos );
EVENT_SetSoldierPosition( pPlanSoldier, sXPos, sYPos );
EVENT_SetSoldierDestination( pPlanSoldier, sGridNo );
pPlanSoldier->bVisible = 1;
pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode;
pPlanSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost;
pPlanSoldier->ubPlannedUIAPCost = (UINT8)pPlanSoldier->bActionPoints;
// Get direction
bDirection = (INT8)gpUIPlannedSoldier->usPathingData[ gpUIPlannedSoldier->usPathDataSize - 1 ];
// Set direction
pPlanSoldier->bDirection = bDirection;
pPlanSoldier->bDesiredDirection = bDirection;
// Set walking animation
ChangeSoldierState( pPlanSoldier, pPlanSoldier->usUIMovementMode, 0, FALSE );
// Change selected soldier
gusSelectedSoldier = (UINT16)pPlanSoldier->ubID;
// Change global planned mode to this guy!
gpUIPlannedSoldier = pPlanSoldier;
gubNumUIPlannedMoves++;
gfPlotNewMovement = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Adding Merc Move to Plan" );
}
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Merc will not have enough action points" );
}
}
else if ( ubPlanID == UIPLAN_ACTION_FIRE )
{
sAPCost = CalcTotalAPsToAttack( gpUIPlannedSoldier, sGridNo, TRUE, (INT8)(gpUIPlannedSoldier->bShownAimTime /2) );
// Get XY from Gridno
ConvertGridNoToCenterCellXY( sGridNo, &sXPos, &sYPos );
// If this is a player guy, show message about no APS
if ( EnoughPoints( gpUIPlannedSoldier, sAPCost, 0, FALSE ) )
{
// CHECK IF WE ARE A PLANNED SOLDIER OR NOT< IF SO< CREATE!
if ( gpUIPlannedSoldier->ubID < MAX_NUM_SOLDIERS )
{
memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
MercCreateStruct.bTeam = SOLDIER_CREATE_AUTO_TEAM;
MercCreateStruct.ubProfile = NO_PROFILE;
MercCreateStruct.fPlayerPlan = TRUE;
MercCreateStruct.bBodyType = gpUIPlannedSoldier->ubBodyType;
MercCreateStruct.sInsertionGridNo = sGridNo;
// Get Grid Corrdinates of mouse
if ( TacticalCreateSoldier( &MercCreateStruct, &ubNewIndex ) )
{
// Get pointer to soldier
GetSoldier( &pPlanSoldier, (UINT16)ubNewIndex );
pPlanSoldier->sPlannedTargetX = -1;
pPlanSoldier->sPlannedTargetY = -1;
// Compare OPPLISTS!
// Set ones we don't know about but do now back to old ( ie no new guys )
for (iLoop = 0; iLoop < MAX_NUM_SOLDIERS; iLoop++ )
{
if ( gpUIPlannedSoldier->bOppList[ iLoop ] < 0 )
{
pPlanSoldier->bOppList[ iLoop ] = gpUIPlannedSoldier->bOppList[ iLoop ];
}
}
EVENT_SetSoldierPosition( pPlanSoldier, gpUIPlannedSoldier->dXPos, gpUIPlannedSoldier->dYPos );
EVENT_SetSoldierDestination( pPlanSoldier, gpUIPlannedSoldier->sGridNo );
pPlanSoldier->bVisible = 1;
pPlanSoldier->usUIMovementMode = gpUIPlannedSoldier->usUIMovementMode;
pPlanSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost;
pPlanSoldier->ubPlannedUIAPCost = (UINT8)pPlanSoldier->bActionPoints;
// Get direction
bDirection = (INT8)gpUIPlannedSoldier->usPathingData[ gpUIPlannedSoldier->usPathDataSize - 1 ];
// Set direction
pPlanSoldier->bDirection = bDirection;
pPlanSoldier->bDesiredDirection = bDirection;
// Set walking animation
ChangeSoldierState( pPlanSoldier, pPlanSoldier->usUIMovementMode, 0, FALSE );
// Change selected soldier
gusSelectedSoldier = (UINT16)pPlanSoldier->ubID;
// Change global planned mode to this guy!
gpUIPlannedSoldier = pPlanSoldier;
gubNumUIPlannedMoves++;
}
}
gpUIPlannedSoldier->bActionPoints = gpUIPlannedSoldier->bActionPoints - sAPCost;
gpUIPlannedSoldier->ubPlannedUIAPCost = (UINT8)gpUIPlannedSoldier->bActionPoints;
// Get direction from gridno
bDirection = (INT8)GetDirectionFromGridNo( sGridNo, gpUIPlannedSoldier );
// Set direction
gpUIPlannedSoldier->bDirection = bDirection;
gpUIPlannedSoldier->bDesiredDirection = bDirection;
// Set to shooting animation
SelectPausedFireAnimation( gpUIPlannedSoldier );
gpUIPlannedSoldier->sPlannedTargetX = sXPos;
gpUIPlannedSoldier->sPlannedTargetY = sYPos;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Adding Merc Shoot to Plan" );
}
else
{
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Merc will not have enough action points" );
}
}
return( TRUE );
}
void EndUIPlan( )
{
int cnt;
SOLDIERTYPE *pSoldier;
// Zero out any planned soldiers
for( cnt = MAX_NUM_SOLDIERS; cnt < TOTAL_SOLDIERS; cnt++ )
{
pSoldier = MercPtrs[ cnt ];
if ( pSoldier->bActive )
{
if ( pSoldier->sPlannedTargetX != -1 )
{
SetRenderFlags(RENDER_FLAG_FULL );
}
TacticalRemoveSoldier( pSoldier->ubID );
}
}
gfInUIPlanMode = FALSE;
gusSelectedSoldier = gpUIStartPlannedSoldier->ubID;
gfPlotNewMovement = TRUE;
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"Leaving Planning Mode" );
}
BOOLEAN InUIPlanMode( )
{
return( gfInUIPlanMode );
}
void SelectPausedFireAnimation( SOLDIERTYPE *pSoldier )
{
// Determine which animation to do...depending on stance and gun in hand...
switch ( gAnimControl[ pSoldier->usAnimState ].ubEndHeight )
{
case ANIM_STAND:
if ( pSoldier->bDoBurst > 0 )
{
ChangeSoldierState( pSoldier, STANDING_BURST, 2 , FALSE );
}
else
{
ChangeSoldierState( pSoldier, SHOOT_RIFLE_STAND, 2 , FALSE );
}
break;
case ANIM_PRONE:
ChangeSoldierState( pSoldier, SHOOT_RIFLE_PRONE, 2 , FALSE );
break;
case ANIM_CROUCH:
ChangeSoldierState( pSoldier, SHOOT_RIFLE_CROUCH, 2 , FALSE );
break;
}
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef __HANDLEUIPLAN_H
#define __HANDLEUIPLAN_H
#include "types.h"
#include "Soldier Control.h"
#define UIPLAN_ACTION_MOVETO 1
#define UIPLAN_ACTION_FIRE 2
BOOLEAN BeginUIPlan( SOLDIERTYPE *pSoldier );
BOOLEAN AddUIPlan( UINT16 sGridNo, UINT8 ubPlanID );
void EndUIPlan( );
BOOLEAN InUIPlanMode( );
#endif
File diff suppressed because it is too large Load Diff
+346
View File
@@ -0,0 +1,346 @@
#ifndef _HANDLE_UI_
#define _HANDLE_UI_
#include "input.h"
#include "Soldier Control.h"
// DEFINES
#define UIEVENT_SINGLEEVENT 0x00000002
#define UIEVENT_SNAPMOUSE 0x00000008
#define NO_GUY_SELECTION 0
#define SELECTED_GUY_SELECTION 1
#define NONSELECTED_GUY_SELECTION 2
#define ENEMY_GUY_SELECTION 3
#define MOUSE_MOVING_IN_TILE 0x00000001
#define MOUSE_MOVING 0x00000002
#define MOUSE_MOVING_NEW_TILE 0x00000004
#define MOUSE_STATIONARY 0x00000008
#define MOVEUI_TARGET_INTTILES 1
#define MOVEUI_TARGET_ITEMS 2
#define MOVEUI_TARGET_MERCS 3
#define MOVEUI_TARGET_MERCSFORAID 5
#define MOVEUI_TARGET_WIREFENCE 6
#define MOVEUI_TARGET_BOMB 7
#define MOVEUI_TARGET_STEAL 8
#define MOVEUI_TARGET_REPAIR 9
#define MOVEUI_TARGET_JAR 10
#define MOVEUI_TARGET_CAN 11
#define MOVEUI_TARGET_REFUEL 12
#define MOVEUI_RETURN_ON_TARGET_MERC 1
typedef enum
{
DONT_CHANGEMODE,
IDLE_MODE,
MOVE_MODE,
ACTION_MODE,
MENU_MODE,
POPUP_MODE,
CONFIRM_MOVE_MODE,
ADJUST_STANCE_MODE,
CONFIRM_ACTION_MODE,
HANDCURSOR_MODE,
GETTINGITEM_MODE,
ENEMYS_TURN_MODE,
LOOKCURSOR_MODE,
TALKINGMENU_MODE,
TALKCURSOR_MODE,
LOCKUI_MODE,
OPENDOOR_MENU_MODE,
LOCKOURTURN_UI_MODE,
EXITSECTORMENU_MODE,
RUBBERBAND_MODE,
JUMPOVER_MODE,
} UI_MODE;
typedef UINT32 (*UI_HANDLEFNC)( struct TAG_UI_EVENT* );
typedef struct TAG_UI_EVENT
{
UINT32 uiFlags;
UI_MODE ChangeToUIMode;
UI_HANDLEFNC HandleEvent;
BOOLEAN fFirstTime;
BOOLEAN fDoneMenu;
UINT32 uiMenuPreviousMode;
UINT32 uiParams[3];
} UI_EVENT;
// EVENT ENUMERATION
typedef enum
{
I_DO_NOTHING,
I_EXIT,
I_NEW_MERC,
I_NEW_BADMERC,
I_SELECT_MERC,
I_ENTER_EDIT_MODE,
I_ENTER_PALEDIT_MODE,
I_ENDTURN,
I_TESTHIT,
I_CHANGELEVEL,
I_ON_TERRAIN,
I_CHANGE_TO_IDLE,
I_LOADLEVEL,
I_SOLDIERDEBUG,
I_LOSDEBUG,
I_LEVELNODEDEBUG,
I_GOTODEMOMODE,
I_LOADFIRSTLEVEL,
I_LOADSECONDLEVEL,
I_LOADTHIRDLEVEL,
I_LOADFOURTHLEVEL,
I_LOADFIFTHLEVEL,
ET_ON_TERRAIN,
ET_ENDENEMYS_TURN,
M_ON_TERRAIN,
M_CHANGE_TO_ACTION,
M_CHANGE_TO_HANDMODE,
M_CYCLE_MOVEMENT,
M_CYCLE_MOVE_ALL,
M_CHANGE_TO_ADJPOS_MODE,
POPUP_DOMESSAGE,
A_ON_TERRAIN,
A_CHANGE_TO_MOVE,
A_CHANGE_TO_CONFIM_ACTION,
A_END_ACTION,
U_MOVEMENT_MENU,
U_POSITION_MENU,
C_WAIT_FOR_CONFIRM,
C_MOVE_MERC,
C_ON_TERRAIN,
PADJ_ADJUST_STANCE,
CA_ON_TERRAIN,
CA_MERC_SHOOT,
CA_END_CONFIRM_ACTION,
HC_ON_TERRAIN,
G_GETTINGITEM,
LC_ON_TERRAIN,
LC_CHANGE_TO_LOOK,
LC_LOOK,
TA_TALKINGMENU,
T_ON_TERRAIN,
T_CHANGE_TO_TALKING,
LU_ON_TERRAIN,
LU_BEGINUILOCK,
LU_ENDUILOCK,
OP_OPENDOORMENU,
LA_ON_TERRAIN,
LA_BEGINUIOURTURNLOCK,
LA_ENDUIOUTURNLOCK,
EX_EXITSECTORMENU,
RB_ON_TERRAIN,
JP_ON_TERRAIN,
JP_JUMP,
NUM_UI_EVENTS
} UI_EVENT_DEFINES;
typedef BOOLEAN (*UIKEYBOARD_HOOK)( InputAtom *pInputEvent );
// GLOBAL EVENT STRUCT
extern UI_EVENT gEvents[ NUM_UI_EVENTS ];
// GLOBAL STATUS VARS
extern UI_MODE gCurrentUIMode;
extern UI_MODE gOldUIMode;
extern UINT32 guiCurrentEvent;
extern INT16 gsSelectedLevel;
extern BOOLEAN gfPlotNewMovement;
extern UINT32 guiPendingOverrideEvent;
// GLOBALS
extern BOOLEAN gfUIDisplayActionPoints;
extern BOOLEAN gfUIDisplayActionPointsInvalid;
extern BOOLEAN gfUIDisplayActionPointsBlack;
extern BOOLEAN gfUIDisplayActionPointsCenter;
extern INT16 gUIDisplayActionPointsOffY;
extern INT16 gUIDisplayActionPointsOffX;
extern BOOLEAN gfUIDoNotHighlightSelMerc;
extern UINT32 guiShowUPDownArrows;
extern BOOLEAN gfUIHandleSelection;
extern BOOLEAN gfUIHandleSelectionAboveGuy;
extern INT16 gsSelectedGridNo;
extern INT16 gsSelectedGuy;
extern BOOLEAN gfUIInDeadlock;
extern UINT8 gUIDeadlockedSoldier;
extern BOOLEAN gfUIMouseOnValidCatcher;
extern UINT8 gubUIValidCatcherID;
extern BOOLEAN gUIUseReverse;
extern BOOLEAN gfUIHandleShowMoveGrid;
extern UINT16 gsUIHandleShowMoveGridLocation;
extern BOOLEAN gfUIDisplayDamage;
extern INT8 gbDamage;
extern UINT16 gsDamageGridNo;
extern BOOLEAN gfFontPopupDo;
extern BOOLEAN gUITargetReady;
extern BOOLEAN gUITargetShotWaiting;
extern UINT16 gsUITargetShotGridNo;
extern INT16 gzLocation[ 20 ];
extern BOOLEAN gfUIBodyHitLocation;
extern UINT8 gsBulletCount;
extern UINT8 gsTotalBulletCount;
extern BOOLEAN gTintBulletCounts;
extern BOOLEAN gfUIAutofireBulletCount;
extern BOOLEAN gfUICtHBar;
extern UINT8 gbCtH;
extern INT16 gzIntTileLocation[ 20 ];
extern BOOLEAN gfUIIntTileLocation;
extern INT16 gzIntTileLocation2[ 20 ];
extern BOOLEAN gfUIIntTileLocation2;
extern BOOLEAN gfUIWaitingForUserSpeechAdvance;
extern BOOLEAN gfUIKeyCheatModeOn;
extern BOOLEAN gfUIAllMoveOn;
extern BOOLEAN gfUICanBeginAllMoveCycle;
extern BOOLEAN gfUIRefreshArrows;
extern BOOLEAN gfUIHandlePhysicsTrajectory;
// GLOBALS FOR FAST LOOKUP FOR FINDING MERCS FROM THE MOUSE
extern BOOLEAN gfUISelectiveTargetFound;
extern UINT16 gusUISelectiveTargetID;
extern UINT32 guiUISelectiveTargetFlags;
extern BOOLEAN gfUIFullTargetFound;
extern UINT16 gusUIFullTargetID;
extern UINT32 guiUIFullTargetFlags;
extern BOOLEAN gfUIConfirmExitArrows;
extern INT16 gsJumpOverGridNo;
extern UINT32 HandleTacticalUI(void);
extern UINT32 UIHandleEndTurn( UI_EVENT *pUIEvent );
extern BOOLEAN gfUIShowCurIntTile;
extern SGPRect gRubberBandRect;
extern BOOLEAN gRubberBandActive;
void EndMenuEvent( UINT32 uiEvent );
void SetUIKeyboardHook( UIKEYBOARD_HOOK KeyboardHookFnc );
void HandleObjectHighlighting( );
extern BOOLEAN gfUIForceReExamineCursorData;
extern INT16 guiCreateGuyIndex;
extern INT16 guiCreateBadGuyIndex;
// FUNCTIONS IN INPUT MODULES
void GetKeyboardInput( UINT32 *puiNewEvent );
void GetPolledKeyboardInput( UINT32 *puiNewEvent );
void GetTBMouseButtonInput( UINT32 *puiNewEvent );
void GetTBMousePositionInput( UINT32 *puiNewEvent );
void QueryTBLeftButton( UINT32 *puiNewEvent );
void QueryTBRightButton( UINT32 *puiNewEvent );
void HandleStanceChangeFromUIKeys( UINT8 ubAnimHeight );
void HandleKeyInputOnEnemyTurn( );
void GetRTMouseButtonInput( UINT32 *puiNewEvent );
void GetRTMousePositionInput( UINT32 *puiNewEvent );
void QueryRTLeftButton( UINT32 *puiNewEvent );
void QueryRTRightButton( UINT32 *puiNewEvent );
void AdjustSoldierCreationStartValues( );
BOOLEAN SelectedMercCanAffordAttack( );
BOOLEAN SelectedMercCanAffordMove( );
void GetMercClimbDirection( UINT8 ubSoldierID, BOOLEAN *pfGoDown, BOOLEAN *pfGoUp );
void ToggleHandCursorMode( UINT32 *puiNewEvent );
void ToggleTalkCursorMode( UINT32 *puiNewEvent );
void ToggleLookCursorMode( UINT32 *puiNewEvent );
void UIHandleSoldierStanceChange( UINT8 ubSoldierID, INT8 bNewStance );
void GetCursorMovementFlags( UINT32 *puiCursorFlags );
BOOLEAN HandleUIMovementCursor( SOLDIERTYPE *pSoldier, UINT32 uiCursorFlags, UINT16 usMapPos, UINT32 uiFlags );
BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier );
BOOLEAN UIOkForItemPickup( SOLDIERTYPE *pSoldier, INT16 sGridNo );
BOOLEAN IsValidTalkableNPCFromMouse( UINT8 *pubSoldierID, BOOLEAN fGive, BOOLEAN fAllowMercs, BOOLEAN fCheckCollapsed );
BOOLEAN IsValidTalkableNPC( UINT8 ubSoldierID, BOOLEAN fGive, BOOLEAN fAllowMercs, BOOLEAN fCheckCollapsed );
BOOLEAN HandleTalkInit( );
BOOLEAN HandleCheckForExitArrowsInput( BOOLEAN fAdjustForConfirm );
void SetUIBusy( UINT8 ubID );
void UnSetUIBusy( UINT8 ubID );
UINT32 UIHandleLUIEndLock( UI_EVENT *pUIEvent );
void BeginDisplayTimedCursor( UINT32 uiCursorID, UINT32 uiDelay );
void HandleHandCursorClick( UINT16 usMapPos, UINT32 *puiNewEvent );
INT8 HandleMoveModeInteractiveClick( UINT16 usMapPos, UINT32 *puiNewEvent );
BOOLEAN HandleUIReloading( SOLDIERTYPE *pSoldier );
UINT32 UIHandleChangeLevel( UI_EVENT *pUIEvent );
BOOLEAN UIHandleOnMerc( BOOLEAN fMovementMode );
void ChangeInterfaceLevel( INT16 sLevel );
void EndRubberBanding( );
void ResetMultiSelection( );
void EndMultiSoldierSelection( BOOLEAN fAcknowledge );
void StopRubberBandedMercFromMoving( );
BOOLEAN SelectedGuyInBusyAnimation( );
void GotoLowerStance( SOLDIERTYPE *pSoldier );
void GotoHeigherStance( SOLDIERTYPE *pSoldier );
BOOLEAN IsValidJumpLocation( SOLDIERTYPE *pSoldier, INT16 sGridNo , BOOLEAN fCheckForPath);
void PopupAssignmentMenuInTactical( SOLDIERTYPE *pSoldier );
void PreventFromTheFreezingBug(SOLDIERTYPE* pSoldier);
#endif
File diff suppressed because it is too large Load Diff
+43
View File
@@ -0,0 +1,43 @@
#ifndef __INTERFACE_CONTROL_H
#define __INTERFACE_CONTROL_H
#define INTERFACE_MAPSCREEN 0x00000001
#define INTERFACE_NORENDERBUTTONS 0x00000002
#define INTERFACE_LOCKEDLEVEL1 0x00000004
#define INTERFACE_SHOPKEEP_INTERFACE 0x00000008
extern UINT32 guiTacticalInterfaceFlags;
void SetTacticalInterfaceFlags( UINT32 uiFlags );
void SetUpInterface( );
void ResetInterface( );
void RenderTopmostTacticalInterface( );
void RenderTacticalInterface( );
void StartViewportOverlays( );
void EndViewportOverlays( );
void LockTacticalInterface( );
void UnLockTacticalInterface( );
void RenderTacticalInterfaceWhileScrolling( );
void EraseInterfaceMenus( BOOLEAN fIgnoreUIUnLock );
// handle paused render of tactical panel, if flag set, OR it in with tactical render flags
// then reset
void HandlePausedTacticalRender( void );
void ResetInterfaceAndUI( );
BOOLEAN AreWeInAUIMenu( );
void HandleTacticalPanelSwitch( );
BOOLEAN InterfaceOKForMeanwhilePopup();
#endif
+788
View File
@@ -0,0 +1,788 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include "sgp.h"
#include "mousesystem.h"
#include "vsurface.h"
#include "wcheck.h"
#include "input.h"
#include "Handle UI.h"
#include "cursors.h"
#include "worlddef.h"
#include "worldman.h"
#include "render dirty.h"
#include "Interface Cursors.h"
#include "interface.h"
#include "Isometric utils.h"
#include "cursors.h"
#include "sys globals.h"
#include "overhead.h"
#include "interface items.h"
#endif
#define DISPLAY_AP_INDEX MOCKFLOOR1
#define SNAPCURSOR_AP_X_STARTVAL 18
#define SNAPCURSOR_AP_Y_STARTVAL 9
#define LOOSE_CURSOR_DELAY 300
static BOOLEAN gfLooseCursorOn = FALSE;
static INT16 gsLooseCursorGridNo = NOWHERE;
static UINT32 guiLooseCursorID = 0;
static UINT32 guiLooseCursorTimeOfLastUpdate = 0;
void HandleLooseCursorDraw( );
void HandleLooseCursorHide( );
UICursor gUICursors[ NUM_UI_CURSORS ] =
{
NO_UICURSOR, 0, 0, 0,
NORMAL_FREEUICURSOR, UICURSOR_FREEFLOWING , CURSOR_NORMAL, 0,
NORMAL_SNAPUICURSOR, UICURSOR_SNAPPING, 0, 0,
MOVE_RUN_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILEAPDEPENDENT | UICURSOR_DONTSHOW2NDLEVEL, CURSOR_RUN1, FIRSTPOINTERS2,
MOVE_WALK_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILEAPDEPENDENT | UICURSOR_DONTSHOW2NDLEVEL | UICURSOR_CENTERAPS, CURSOR_WALK1, FIRSTPOINTERS2,
MOVE_SWAT_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILEAPDEPENDENT | UICURSOR_DONTSHOW2NDLEVEL, CURSOR_SWAT1, FIRSTPOINTERS2,
MOVE_PRONE_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILEAPDEPENDENT | UICURSOR_DONTSHOW2NDLEVEL, CURSOR_PRONE1, FIRSTPOINTERS2,
MOVE_VEHICLE_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILEAPDEPENDENT | UICURSOR_DONTSHOW2NDLEVEL, CURSOR_DRIVEV, FIRSTPOINTERS2,
CONFIRM_MOVE_RUN_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS4,
CONFIRM_MOVE_WALK_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS4,
CONFIRM_MOVE_SWAT_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS4,
CONFIRM_MOVE_PRONE_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS4,
CONFIRM_MOVE_VEHICLE_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS4,
ALL_MOVE_RUN_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS5,
ALL_MOVE_WALK_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS5,
ALL_MOVE_SWAT_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS5,
ALL_MOVE_PRONE_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS5,
ALL_MOVE_VEHICLE_UICURSOR, UICURSOR_SNAPPING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, 0, FIRSTPOINTERS5,
MOVE_REALTIME_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILEAPDEPENDENT | UICURSOR_DONTSHOW2NDLEVEL, VIDEO_NO_CURSOR, FIRSTPOINTERS2,
MOVE_RUN_REALTIME_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, VIDEO_NO_CURSOR, FIRSTPOINTERS7,
CONFIRM_MOVE_REALTIME_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, VIDEO_NO_CURSOR, FIRSTPOINTERS4,
ALL_MOVE_REALTIME_UICURSOR, UICURSOR_FREEFLOWING | UICURSOR_SHOWTILE | UICURSOR_DONTSHOW2NDLEVEL, VIDEO_NO_CURSOR, FIRSTPOINTERS5,
ON_OWNED_MERC_UICURSOR, UICURSOR_SNAPPING, 0, 0,
ON_OWNED_SELMERC_UICURSOR, UICURSOR_SNAPPING, 0, 0,
ACTION_SHOOT_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGET, 0,
ACTION_NOCHANCE_SHOOT_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETDKBLACK, 0,
ACTION_NOCHANCE_BURST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETBURSTDKBLACK, 0,
ACTION_FLASH_TOSS_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGET, 0,
ACTION_TOSS_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGET, 0,
ACTION_RED_TOSS_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETRED, 0,
ACTION_FLASH_SHOOT_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FLASH_TARGET, 0,
ACTION_FLASH_BURST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FLASH_TARGETBURST, 0,
ACTION_TARGETAIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON1, 0,
ACTION_TARGETAIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON2, 0,
ACTION_TARGETAIM3_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON3, 0,
ACTION_TARGETAIM4_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON4, 0,
ACTION_TARGETAIM5_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON5, 0,
ACTION_TARGETAIM6_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON6, 0,
ACTION_TARGETAIM7_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON7, 0,
ACTION_TARGETAIM8_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON8, 0,
ACTION_TARGETAIM8_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETON9, 0,
ACTION_TARGETAIMCANT1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETW1, 0,
ACTION_TARGETAIMCANT2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETW2, 0,
ACTION_TARGETAIMCANT3_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETW3, 0,
ACTION_TARGETAIMCANT4_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETW4, 0,
ACTION_TARGETAIMCANT5_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETW5, 0,
ACTION_TARGETRED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETRED, 0,
ACTION_TARGETBURST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETBURST, 0,
ACTION_TARGETREDBURST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETBURSTRED, 0,
ACTION_TARGETCONFIRMBURST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETBURSTCONFIRM, 0,
ACTION_TARGETAIMFULL_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETWR1, 0,
ACTION_TARGETAIMYELLOW1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETYELLOW1, 0,
ACTION_TARGETAIMYELLOW2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETYELLOW2, 0,
ACTION_TARGETAIMYELLOW3_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETYELLOW3, 0,
ACTION_TARGETAIMYELLOW4_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TARGETYELLOW4, 0,
ACTION_TARGET_RELOADING, UICURSOR_FREEFLOWING, CURSOR_TARGETBLACK, 0,
ACTION_PUNCH_GRAY, UICURSOR_FREEFLOWING, CURSOR_PUNCHGRAY, 0,
ACTION_PUNCH_RED, UICURSOR_FREEFLOWING, CURSOR_PUNCHRED, 0,
ACTION_PUNCH_RED_AIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_PUNCHRED_ON1, 0,
ACTION_PUNCH_RED_AIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_PUNCHRED_ON2, 0,
ACTION_PUNCH_YELLOW_AIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_PUNCHYELLOW_ON1, 0,
ACTION_PUNCH_YELLOW_AIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_PUNCHYELLOW_ON2, 0,
ACTION_PUNCH_NOGO_AIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_PUNCHNOGO_ON1, 0,
ACTION_PUNCH_NOGO_AIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_PUNCHNOGO_ON2, 0,
ACTION_FIRSTAID_GRAY, UICURSOR_FREEFLOWING, CURSOR_CROSS_REG, 0,
ACTION_FIRSTAID_RED, UICURSOR_FREEFLOWING, CURSOR_CROSS_ACTIVE, 0,
ACTION_OPEN, UICURSOR_FREEFLOWING, CURSOR_HANDGRAB, 0,
CANNOT_MOVE_UICURSOR, UICURSOR_SNAPPING, 0, 0,
NORMALHANDCURSOR_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_NORMGRAB, 0,
OKHANDCURSOR_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HANDGRAB, 0,
KNIFE_REG_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_REG, 0,
KNIFE_HIT_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_HIT, 0,
KNIFE_HIT_AIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_HIT_ON1, 0,
KNIFE_HIT_AIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_HIT_ON2, 0,
KNIFE_YELLOW_AIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_YELLOW_ON1, 0,
KNIFE_YELLOW_AIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_YELLOW_ON2, 0,
KNIFE_NOGO_AIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_NOGO_ON1, 0,
KNIFE_NOGO_AIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_KNIFE_NOGO_ON2, 0,
LOOK_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_LOOK, 0,
TALK_NA_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_TALK, 0,
TALK_A_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_REDTALK, 0,
TALK_OUT_RANGE_NA_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FLASH_TALK, CURSOR_BLACKTALK,
TALK_OUT_RANGE_A_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FLASH_REDTALK, CURSOR_BLACKTALK,
EXIT_NORTH_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_EXIT_NORTH, 0,
EXIT_SOUTH_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_EXIT_SOUTH, 0,
EXIT_EAST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_EXIT_EAST, 0,
EXIT_WEST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_EXIT_WEST, 0,
EXIT_GRID_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_EXIT_GRID, 0,
NOEXIT_NORTH_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_NOEXIT_NORTH, 0,
NOEXIT_SOUTH_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_NOEXIT_SOUTH, 0,
NOEXIT_EAST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_NOEXIT_EAST, 0,
NOEXIT_WEST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_NOEXIT_WEST, 0,
NOEXIT_GRID_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_NOEXIT_GRID, 0,
CONFIRM_EXIT_NORTH_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_CONEXIT_NORTH, 0,
CONFIRM_EXIT_SOUTH_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_CONEXIT_SOUTH, 0,
CONFIRM_EXIT_EAST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_CONEXIT_EAST, 0,
CONFIRM_EXIT_WEST_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_CONEXIT_WEST, 0,
CONFIRM_EXIT_GRID_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_CONEXIT_GRID, 0,
GOOD_WIRECUTTER_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_GOOD_WIRECUT, 0,
BAD_WIRECUTTER_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_BAD_WIRECUT, 0,
GOOD_REPAIR_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_REPAIR, 0,
BAD_REPAIR_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_REPAIRRED, 0,
GOOD_RELOAD_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_GOOD_RELOAD, 0,
BAD_RELOAD_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_BAD_RELOAD, 0,
GOOD_JAR_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_JARRED, 0,
BAD_JAR_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_JAR, 0,
GOOD_THROW_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_GOOD_THROW, 0,
BAD_THROW_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_BAD_THROW, 0,
RED_THROW_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_RED_THROW, 0,
FLASH_THROW_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FLASH_THROW, 0,
ACTION_THROWAIM1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON1, 0,
ACTION_THROWAIM2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON2, 0,
ACTION_THROWAIM3_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON3, 0,
ACTION_THROWAIM4_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON4, 0,
ACTION_THROWAIM5_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON5, 0,
ACTION_THROWAIM6_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON6, 0,
ACTION_THROWAIM7_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON7, 0,
ACTION_THROWAIM8_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON8, 0,
ACTION_THROWAIM8_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKON9, 0,
ACTION_THROWAIMCANT1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKW1, 0,
ACTION_THROWAIMCANT2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKW2, 0,
ACTION_THROWAIMCANT3_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKW3, 0,
ACTION_THROWAIMCANT4_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKW4, 0,
ACTION_THROWAIMCANT5_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKW5, 0,
ACTION_THROWAIMFULL_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKWR1, 0,
ACTION_THROWAIMYELLOW1_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKYELLOW1, 0,
ACTION_THROWAIMYELLOW2_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKYELLOW2, 0,
ACTION_THROWAIMYELLOW3_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKYELLOW3, 0,
ACTION_THROWAIMYELLOW4_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_THROWKYELLOW4, 0,
THROW_ITEM_GOOD_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_ITEM_GOOD_THROW, 0,
THROW_ITEM_BAD_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_ITEM_BAD_THROW, 0,
THROW_ITEM_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_ITEM_RED_THROW, 0,
THROW_ITEM_FLASH_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_ITEM_FLASH_THROW, 0,
PLACE_BOMB_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_BOMB_GRAY, 0,
PLACE_BOMB_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_BOMB_RED, 0,
PLACE_REMOTE_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_REMOTE_GRAY, 0,
PLACE_REMOTE_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_REMOTE_RED, 0,
PLACE_TINCAN_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_CAN, 0,
PLACE_TINCAN_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_CANRED, 0,
ENTER_VEHICLE_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_ENTERV, 0,
INVALID_ACTION_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_INVALID_ACTION, 0,
FLOATING_X_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_X, 0,
EXCHANGE_PLACES_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_EXCHANGE_PLACES, 0,
JUMP_OVER_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_JUMP_OVER, 0,
REFUEL_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FUEL, 0,
REFUEL_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_FUEL_RED, 0,
};
UINT32 guiCurUICursor = NO_UICURSOR;
UINT32 guiOldUICursor = NO_UICURSOR;
UINT16 gusCurMousePos;
UINT16 gusTargetDropPos;
BOOLEAN gfTargetDropPos = FALSE;
// LOCAL FUNCTIONS
void EraseSnappingCursor( );
void DrawSnappingCursor( );
BOOLEAN SetUICursor( UINT32 uiNewCursor )
{
guiOldUICursor = guiCurUICursor;
guiCurUICursor = uiNewCursor;
return( TRUE );
}
BOOLEAN DrawUICursor( )
{
UINT16 usMapPos;
static BOOLEAN fHideCursor = FALSE;
LEVELNODE *pNode;
UINT16 usTileCursor;
//RaiseMouseToLevel( (INT8)gsInterfaceLevel );
HandleLooseCursorDraw( );
// OK, WE OVERRIDE HERE CURSOR DRAWING FOR THINGS LIKE
if ( gpItemPointer != NULL )
{
MSYS_ChangeRegionCursor( &gViewportRegion , VIDEO_NO_CURSOR );
// Check if we are in the viewport region...
if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
{
DrawItemTileCursor( );
}
else
{
DrawItemFreeCursor( );
}
return( TRUE );
}
if (GetMouseMapPos( (INT16 *)&usMapPos) )
{
gusCurMousePos = usMapPos;
if ( guiCurUICursor == NO_UICURSOR )
{
MSYS_ChangeRegionCursor( &gViewportRegion , VIDEO_NO_CURSOR );
return( TRUE );
}
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_SHOWTILE )
{
if ( gsInterfaceLevel == I_ROOF_LEVEL )
{
pNode = AddTopmostToTail( gusCurMousePos, GetSnapCursorIndex( FIRSTPOINTERS3 ) );
}
else
{
pNode = AddTopmostToTail( gusCurMousePos, GetSnapCursorIndex( gUICursors[ guiCurUICursor ].usAdditionalData ) );
}
pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
if ( gsInterfaceLevel == I_ROOF_LEVEL )
{
// Put one on the roof as well
AddOnRoofToHead( gusCurMousePos, GetSnapCursorIndex( gUICursors[ guiCurUICursor ].usAdditionalData ) );
gpWorldLevelData[gusCurMousePos].pOnRoofHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gusCurMousePos].pOnRoofHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
gfTargetDropPos = FALSE;
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_FREEFLOWING && !( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_DONTSHOW2NDLEVEL ) )
{
gfTargetDropPos = TRUE;
gusTargetDropPos = gusCurMousePos;
if ( gsInterfaceLevel == I_ROOF_LEVEL )
{
// If we are over a target, jump to that....
if ( gfUIFullTargetFound )
{
gusTargetDropPos = MercPtrs[ gusUIFullTargetID ]->sGridNo;
}
// Put tile on the floor
AddTopmostToTail( gusTargetDropPos, FIRSTPOINTERS14 );
gpWorldLevelData[ gusTargetDropPos ].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[ gusTargetDropPos ].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_SHOWTILEAPDEPENDENT )
{
// Add depending on AP status
usTileCursor = gUICursors[ guiCurUICursor ].usAdditionalData;
// ATE; Is the current guy in steath mode?
if ( gusSelectedSoldier != NOBODY )
{
if ( MercPtrs[ gusSelectedSoldier ]->bStealthMode )
{
usTileCursor = FIRSTPOINTERS9;
}
}
if ( gfUIDisplayActionPointsInvalid || gsCurrentActionPoints == 0 )
{
usTileCursor = FIRSTPOINTERS6;
// ATE; Is the current guy in steath mode?
if ( gusSelectedSoldier != NOBODY )
{
if ( MercPtrs[ gusSelectedSoldier ]->bStealthMode )
{
usTileCursor = FIRSTPOINTERS10;
}
}
}
if ( gsInterfaceLevel == I_ROOF_LEVEL )
{
pNode = AddTopmostToTail( gusCurMousePos, GetSnapCursorIndex( FIRSTPOINTERS14 ) );
}
else
{
pNode = AddTopmostToTail( gusCurMousePos, GetSnapCursorIndex( usTileCursor ) );
}
pNode->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNode->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
if ( gsInterfaceLevel == I_ROOF_LEVEL )
{
// Put one on the roof as well
AddOnRoofToHead( gusCurMousePos, GetSnapCursorIndex( usTileCursor ) );
gpWorldLevelData[gusCurMousePos].pOnRoofHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gusCurMousePos].pOnRoofHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
// If snapping - remove from main viewport
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_SNAPPING )
{
// Hide mouse region cursor
MSYS_ChangeRegionCursor( &gViewportRegion , VIDEO_NO_CURSOR );
// Set Snapping Cursor
DrawSnappingCursor( );
}
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_FREEFLOWING )
{
switch( guiCurUICursor )
{
case MOVE_VEHICLE_UICURSOR:
// Set position for APS
gfUIDisplayActionPointsCenter = FALSE;
gUIDisplayActionPointsOffX = 16;
gUIDisplayActionPointsOffY = 14;
break;
case MOVE_WALK_UICURSOR:
case MOVE_RUN_UICURSOR:
// Set position for APS
gfUIDisplayActionPointsCenter = FALSE;
gUIDisplayActionPointsOffX = 16;
gUIDisplayActionPointsOffY = 14;
break;
case MOVE_SWAT_UICURSOR:
// Set position for APS
gfUIDisplayActionPointsCenter = FALSE;
gUIDisplayActionPointsOffX = 16;
gUIDisplayActionPointsOffY = 10;
break;
case MOVE_PRONE_UICURSOR:
// Set position for APS
gfUIDisplayActionPointsCenter = FALSE;
gUIDisplayActionPointsOffX = 16;
gUIDisplayActionPointsOffY = 9;
break;
}
fHideCursor = FALSE;
if ( !fHideCursor )
{
MSYS_ChangeRegionCursor( &gViewportRegion , gUICursors[ guiCurUICursor ].usFreeCursorName );
}
else
{
// Hide
MSYS_ChangeRegionCursor( &gViewportRegion , VIDEO_NO_CURSOR );
}
}
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_CENTERAPS )
{
gfUIDisplayActionPointsCenter = TRUE;
}
}
return( TRUE );
}
BOOLEAN HideUICursor( )
{
HandleLooseCursorHide( );
// OK, WE OVERRIDE HERE CURSOR DRAWING FOR THINGS LIKE
if ( gpItemPointer != NULL )
{
// Check if we are in the viewport region...
if ( gViewportRegion.uiFlags & MSYS_MOUSE_IN_AREA )
{
HideItemTileCursor( );
return( TRUE );
}
}
if ( guiCurUICursor == NO_UICURSOR )
{
//Do nothing here
return( TRUE );
}
if ( gUICursors[ guiCurUICursor ].uiFlags & ( UICURSOR_SHOWTILE | UICURSOR_SHOWTILEAPDEPENDENT ) )
{
RemoveAllTopmostsOfTypeRange( gusCurMousePos, FIRSTPOINTERS, FIRSTPOINTERS );
RemoveAllOnRoofsOfTypeRange( gusCurMousePos, FIRSTPOINTERS, FIRSTPOINTERS );
}
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_FREEFLOWING && !( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_DONTSHOW2NDLEVEL ) )
{
if ( gsInterfaceLevel == I_ROOF_LEVEL )
{
RemoveTopmost( gusCurMousePos, FIRSTPOINTERS14 );
RemoveTopmost( gusCurMousePos, FIRSTPOINTERS9 );
if ( gfTargetDropPos )
{
RemoveTopmost( gusTargetDropPos, FIRSTPOINTERS14 );
RemoveTopmost( gusTargetDropPos, FIRSTPOINTERS9 );
}
}
}
// If snapping - remove from main viewport
if ( ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_SNAPPING ) )
{
// hide Snapping Cursor
EraseSnappingCursor( );
}
if ( gUICursors[ guiCurUICursor ].uiFlags & UICURSOR_FREEFLOWING )
{
// Nothing special here...
}
return( TRUE );
}
void DrawSnappingCursor( )
{
LEVELNODE *pNewUIElem;
SOLDIERTYPE *pSoldier;
static BOOLEAN fShowAP = TRUE;
if ( gusSelectedSoldier != NO_SOLDIER )
{
GetSoldier( &pSoldier, gusSelectedSoldier );
}
// If we are in draw item mode, do nothing here but call the fuctiuon
switch ( guiCurUICursor )
{
case NO_UICURSOR:
break;
case NORMAL_SNAPUICURSOR:
AddTopmostToHead( gusCurMousePos, FIRSTPOINTERS1 );
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
break;
case ALL_MOVE_RUN_UICURSOR:
case CONFIRM_MOVE_RUN_UICURSOR:
if ( gsInterfaceLevel > 0 )
{
AddUIElem( gusCurMousePos, GOODRUN1, 0, -WALL_HEIGHT - 8, &pNewUIElem );
}
else
{
AddUIElem( gusCurMousePos, GOODRUN1, 0, 0, &pNewUIElem );
}
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
break;
case ALL_MOVE_WALK_UICURSOR:
case CONFIRM_MOVE_WALK_UICURSOR:
if ( gsInterfaceLevel > 0 )
{
AddUIElem( gusCurMousePos, GOODWALK1, 0, -WALL_HEIGHT - 8, &pNewUIElem );
}
else
{
AddUIElem( gusCurMousePos, GOODWALK1, 0, 0, &pNewUIElem );
}
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
break;
case ALL_MOVE_SWAT_UICURSOR:
case CONFIRM_MOVE_SWAT_UICURSOR:
if ( gsInterfaceLevel > 0 )
{
AddUIElem( gusCurMousePos, GOODSWAT1, 0, -WALL_HEIGHT - 8, &pNewUIElem );
}
else
{
AddUIElem( gusCurMousePos, GOODSWAT1, 0, 0, &pNewUIElem );
}
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
break;
case ALL_MOVE_PRONE_UICURSOR:
case CONFIRM_MOVE_PRONE_UICURSOR:
if ( gsInterfaceLevel > 0 )
{
AddUIElem( gusCurMousePos, GOODPRONE1, 0, -WALL_HEIGHT - 8 - 6, &pNewUIElem );
}
else
{
AddUIElem( gusCurMousePos, GOODPRONE1, 0, -6, &pNewUIElem );
}
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
break;
case ALL_MOVE_VEHICLE_UICURSOR:
case CONFIRM_MOVE_VEHICLE_UICURSOR:
if ( gsInterfaceLevel > 0 )
{
AddUIElem( gusCurMousePos, VEHICLEMOVE1, 0, -WALL_HEIGHT - 8, &pNewUIElem );
}
else
{
AddUIElem( gusCurMousePos, VEHICLEMOVE1, 0, 0, &pNewUIElem );
}
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
break;
case MOVE_REALTIME_UICURSOR:
break;
case CANNOT_MOVE_UICURSOR:
if ( gsInterfaceLevel > 0 )
{
AddUIElem( gusCurMousePos, BADMARKER1, 0, -WALL_HEIGHT - 8, &pNewUIElem );
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
if ( gGameSettings.fOptions[ TOPTION_3D_CURSOR ] )
{
AddTopmostToHead( gusCurMousePos, FIRSTPOINTERS13 );
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
AddOnRoofToHead( gusCurMousePos, FIRSTPOINTERS14 );
gpWorldLevelData[gusCurMousePos].pOnRoofHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gusCurMousePos].pOnRoofHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
else
{
AddTopmostToHead( gusCurMousePos, BADMARKER1 );
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
if ( gGameSettings.fOptions[ TOPTION_3D_CURSOR ] )
{
AddTopmostToHead( gusCurMousePos, FIRSTPOINTERS13 );
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubShadeLevel=DEFAULT_SHADE_LEVEL;
gpWorldLevelData[gusCurMousePos].pTopmostHead->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
break;
}
// Add action points
if ( gfUIDisplayActionPoints )
{
if ( gfUIDisplayActionPointsInvalid )
{
if ( COUNTERDONE( CURSORFLASH ) )
{
RESETCOUNTER( CURSORFLASH );
fShowAP = !fShowAP;
}
}
else
{
fShowAP = TRUE;
}
if ( gsInterfaceLevel > 0 )
{
AddUIElem( gusCurMousePos, DISPLAY_AP_INDEX, SNAPCURSOR_AP_X_STARTVAL, SNAPCURSOR_AP_Y_STARTVAL - WALL_HEIGHT - 10, &pNewUIElem );
}
else
{
AddUIElem( gusCurMousePos, DISPLAY_AP_INDEX, SNAPCURSOR_AP_X_STARTVAL, SNAPCURSOR_AP_Y_STARTVAL, &pNewUIElem );
}
pNewUIElem->uiFlags |= LEVELNODE_DISPLAY_AP;
pNewUIElem->uiAPCost = gsCurrentActionPoints;
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
if ( !fShowAP )
{
gfUIDisplayActionPointsBlack = TRUE;
}
}
}
void EraseSnappingCursor( )
{
RemoveAllTopmostsOfTypeRange( gusCurMousePos, MOCKFLOOR, MOCKFLOOR );
RemoveAllTopmostsOfTypeRange( gusCurMousePos, FIRSTPOINTERS, LASTPOINTERS );
RemoveAllObjectsOfTypeRange( gusCurMousePos, FIRSTPOINTERS, LASTPOINTERS );
RemoveAllOnRoofsOfTypeRange( gusCurMousePos, FIRSTPOINTERS, LASTPOINTERS );
RemoveAllOnRoofsOfTypeRange( gusCurMousePos, MOCKFLOOR, MOCKFLOOR );
}
void StartLooseCursor( INT16 sGridNo, UINT32 uiCursorID )
{
gfLooseCursorOn = TRUE;
guiLooseCursorID = uiCursorID;
guiLooseCursorTimeOfLastUpdate = GetJA2Clock( );
gsLooseCursorGridNo = sGridNo;
}
void HandleLooseCursorDraw( )
{
LEVELNODE *pNewUIElem;
if ( ( GetJA2Clock( ) - guiLooseCursorTimeOfLastUpdate ) > LOOSE_CURSOR_DELAY )
{
gfLooseCursorOn = FALSE;
}
if ( gfLooseCursorOn )
{
AddUIElem( gsLooseCursorGridNo, FIRSTPOINTERS4, 0, 0, &pNewUIElem );
pNewUIElem->ubShadeLevel=DEFAULT_SHADE_LEVEL;
pNewUIElem->ubNaturalShadeLevel=DEFAULT_SHADE_LEVEL;
}
}
void HandleLooseCursorHide( )
{
if ( gfLooseCursorOn )
{
RemoveTopmost( gsLooseCursorGridNo, FIRSTPOINTERS4 );
}
}
UINT16 GetSnapCursorIndex( UINT16 usAdditionalData )
{
// OK, this function will get the 'true' index for drawing the cursor....
if ( gGameSettings.fOptions[ TOPTION_3D_CURSOR ] )
{
switch( usAdditionalData )
{
case FIRSTPOINTERS2:
return( FIRSTPOINTERS13 );
break;
case FIRSTPOINTERS3:
return( FIRSTPOINTERS14 );
break;
case FIRSTPOINTERS4:
return( FIRSTPOINTERS15 );
break;
case FIRSTPOINTERS5:
return( FIRSTPOINTERS16 );
break;
case FIRSTPOINTERS6:
return( FIRSTPOINTERS17 );
break;
case FIRSTPOINTERS7:
return( FIRSTPOINTERS18 );
break;
case FIRSTPOINTERS9:
return( FIRSTPOINTERS19 );
break;
case FIRSTPOINTERS10:
return( FIRSTPOINTERS20 );
break;
default:
return( usAdditionalData );
}
}
else
{
return( usAdditionalData );
}
}
+216
View File
@@ -0,0 +1,216 @@
#ifndef __INTERFACE_CURSORS_H
#define __INTERFACE_CURSORS_H
#define UICURSOR_FREEFLOWING 0x00000002
#define UICURSOR_SNAPPING 0x00000004
#define UICURSOR_SHOWTILE 0x00000008
#define UICURSOR_FLASHING 0x00000020
#define UICURSOR_CENTERAPS 0x00000040
#define UICURSOR_SHOWTILEAPDEPENDENT 0x00000080
#define UICURSOR_DONTSHOW2NDLEVEL 0x00000100
typedef enum
{
NO_UICURSOR,
NORMAL_FREEUICURSOR,
NORMAL_SNAPUICURSOR,
MOVE_RUN_UICURSOR,
MOVE_WALK_UICURSOR,
MOVE_SWAT_UICURSOR,
MOVE_PRONE_UICURSOR,
MOVE_VEHICLE_UICURSOR,
CONFIRM_MOVE_RUN_UICURSOR,
CONFIRM_MOVE_WALK_UICURSOR,
CONFIRM_MOVE_SWAT_UICURSOR,
CONFIRM_MOVE_PRONE_UICURSOR,
CONFIRM_MOVE_VEHICLE_UICURSOR,
ALL_MOVE_RUN_UICURSOR,
ALL_MOVE_WALK_UICURSOR,
ALL_MOVE_SWAT_UICURSOR,
ALL_MOVE_PRONE_UICURSOR,
ALL_MOVE_VEHICLE_UICURSOR,
MOVE_REALTIME_UICURSOR,
MOVE_RUN_REALTIME_UICURSOR,
CONFIRM_MOVE_REALTIME_UICURSOR,
ALL_MOVE_REALTIME_UICURSOR,
ON_OWNED_MERC_UICURSOR,
ON_OWNED_SELMERC_UICURSOR,
ACTION_SHOOT_UICURSOR,
ACTION_NOCHANCE_SHOOT_UICURSOR,
ACTION_NOCHANCE_BURST_UICURSOR,
ACTION_FLASH_TOSS_UICURSOR,
ACTION_TOSS_UICURSOR,
ACTION_RED_TOSS_UICURSOR,
ACTION_FLASH_SHOOT_UICURSOR,
ACTION_FLASH_BURST_UICURSOR,
ACTION_TARGETAIM1_UICURSOR,
ACTION_TARGETAIM2_UICURSOR,
ACTION_TARGETAIM3_UICURSOR,
ACTION_TARGETAIM4_UICURSOR,
ACTION_TARGETAIM5_UICURSOR,
ACTION_TARGETAIM6_UICURSOR,
ACTION_TARGETAIM7_UICURSOR,
ACTION_TARGETAIM8_UICURSOR,
ACTION_TARGETAIM9_UICURSOR,
ACTION_TARGETAIMCANT1_UICURSOR,
ACTION_TARGETAIMCANT2_UICURSOR,
ACTION_TARGETAIMCANT3_UICURSOR,
ACTION_TARGETAIMCANT4_UICURSOR,
ACTION_TARGETAIMCANT5_UICURSOR,
ACTION_TARGETRED_UICURSOR,
ACTION_TARGETBURST_UICURSOR,
ACTION_TARGETREDBURST_UICURSOR,
ACTION_TARGETCONFIRMBURST_UICURSOR,
ACTION_TARGETAIMFULL_UICURSOR,
ACTION_TARGETAIMYELLOW1_UICURSOR,
ACTION_TARGETAIMYELLOW2_UICURSOR,
ACTION_TARGETAIMYELLOW3_UICURSOR,
ACTION_TARGETAIMYELLOW4_UICURSOR,
ACTION_TARGET_RELOADING,
ACTION_PUNCH_GRAY,
ACTION_PUNCH_RED,
ACTION_PUNCH_RED_AIM1_UICURSOR,
ACTION_PUNCH_RED_AIM2_UICURSOR,
ACTION_PUNCH_YELLOW_AIM1_UICURSOR,
ACTION_PUNCH_YELLOW_AIM2_UICURSOR,
ACTION_PUNCH_NOGO_AIM1_UICURSOR,
ACTION_PUNCH_NOGO_AIM2_UICURSOR,
ACTION_FIRSTAID_GRAY,
ACTION_FIRSTAID_RED,
ACTION_OPEN,
CANNOT_MOVE_UICURSOR,
NORMALHANDCURSOR_UICURSOR,
OKHANDCURSOR_UICURSOR,
KNIFE_REG_UICURSOR,
KNIFE_HIT_UICURSOR,
KNIFE_HIT_AIM1_UICURSOR,
KNIFE_HIT_AIM2_UICURSOR,
KNIFE_YELLOW_AIM1_UICURSOR,
KNIFE_YELLOW_AIM2_UICURSOR,
KNIFE_NOGO_AIM1_UICURSOR,
KNIFE_NOGO_AIM2_UICURSOR,
LOOK_UICURSOR,
TALK_NA_UICURSOR,
TALK_A_UICURSOR,
TALK_OUT_RANGE_NA_UICURSOR,
TALK_OUT_RANGE_A_UICURSOR,
EXIT_NORTH_UICURSOR,
EXIT_SOUTH_UICURSOR,
EXIT_EAST_UICURSOR,
EXIT_WEST_UICURSOR,
EXIT_GRID_UICURSOR,
NOEXIT_NORTH_UICURSOR,
NOEXIT_SOUTH_UICURSOR,
NOEXIT_EAST_UICURSOR,
NOEXIT_WEST_UICURSOR,
NOEXIT_GRID_UICURSOR,
CONFIRM_EXIT_NORTH_UICURSOR,
CONFIRM_EXIT_SOUTH_UICURSOR,
CONFIRM_EXIT_EAST_UICURSOR,
CONFIRM_EXIT_WEST_UICURSOR,
CONFIRM_EXIT_GRID_UICURSOR,
GOOD_WIRECUTTER_UICURSOR,
BAD_WIRECUTTER_UICURSOR,
GOOD_REPAIR_UICURSOR,
BAD_REPAIR_UICURSOR,
GOOD_RELOAD_UICURSOR,
BAD_RELOAD_UICURSOR,
GOOD_JAR_UICURSOR,
BAD_JAR_UICURSOR,
GOOD_THROW_UICURSOR,
BAD_THROW_UICURSOR,
RED_THROW_UICURSOR,
FLASH_THROW_UICURSOR,
ACTION_THROWAIM1_UICURSOR,
ACTION_THROWAIM2_UICURSOR,
ACTION_THROWAIM3_UICURSOR,
ACTION_THROWAIM4_UICURSOR,
ACTION_THROWAIM5_UICURSOR,
ACTION_THROWAIM6_UICURSOR,
ACTION_THROWAIM7_UICURSOR,
ACTION_THROWAIM8_UICURSOR,
ACTION_THROWAIM9_UICURSOR,
ACTION_THROWAIMCANT1_UICURSOR,
ACTION_THROWAIMCANT2_UICURSOR,
ACTION_THROWAIMCANT3_UICURSOR,
ACTION_THROWAIMCANT4_UICURSOR,
ACTION_THROWAIMCANT5_UICURSOR,
ACTION_THROWAIMFULL_UICURSOR,
ACTION_THROWAIMYELLOW1_UICURSOR,
ACTION_THROWAIMYELLOW2_UICURSOR,
ACTION_THROWAIMYELLOW3_UICURSOR,
ACTION_THROWAIMYELLOW4_UICURSOR,
THROW_ITEM_GOOD_UICURSOR,
THROW_ITEM_BAD_UICURSOR,
THROW_ITEM_RED_UICURSOR,
THROW_ITEM_FLASH_UICURSOR,
PLACE_BOMB_GREY_UICURSOR,
PLACE_BOMB_RED_UICURSOR,
PLACE_REMOTE_GREY_UICURSOR,
PLACE_REMOTE_RED_UICURSOR,
PLACE_TINCAN_GREY_UICURSOR,
PLACE_TINCAN_RED_UICURSOR,
ENTER_VEHICLE_UICURSOR,
INVALID_ACTION_UICURSOR,
FLOATING_X_UICURSOR,
EXCHANGE_PLACES_UICURSOR,
JUMP_OVER_UICURSOR,
REFUEL_GREY_UICURSOR,
REFUEL_RED_UICURSOR,
NUM_UI_CURSORS
} UICursorDefines;
typedef struct
{
UINT32 uiCursorID;
UINT32 uiFlags;
UINT16 usFreeCursorName;
UINT16 usAdditionalData;
} UICursor;
extern UICursor gUICursors[ NUM_UI_CURSORS ];
BOOLEAN SetUICursor( UINT32 uiNewCursor );
BOOLEAN DrawUICursor( );
BOOLEAN HideUICursor( );
extern UINT16 gusCurMousePos;
UINT16 GetSnapCursorIndex( UINT16 usAdditionalData );
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+159
View File
@@ -0,0 +1,159 @@
#ifndef __INTERFACE_ITEMS_H
#define __INTERFACE_ITEMS_H
#include "items.h"
#include "Handle Items.h"
// DEFINES FOR ITEM SLOT SIZES IN PIXELS
#define BIG_INV_SLOT_WIDTH 61
#define BIG_INV_SLOT_HEIGHT 22
#define SM_INV_SLOT_WIDTH 30
#define SM_INV_SLOT_HEIGHT 23
#define VEST_INV_SLOT_WIDTH 43
#define VEST_INV_SLOT_HEIGHT 24
#define LEGS_INV_SLOT_WIDTH 43
#define LEGS_INV_SLOT_HEIGHT 24
#define HEAD_INV_SLOT_WIDTH 43
#define HEAD_INV_SLOT_HEIGHT 24
// A STRUCT USED INTERNALLY FOR INV SLOT REGIONS
typedef struct
{
BOOLEAN fBigPocket;
INT16 sBarDx;
INT16 sBarDy;
INT16 sWidth;
INT16 sHeight;
INT16 sX; // starts at 0, gets set via InitInvSlotInterface()
INT16 sY; // starts at 0, gets set via InitInvSlotInterface()
} INV_REGIONS;
// USED TO SETUP REGION POSITIONS, ETC
typedef struct
{
INT16 sX;
INT16 sY;
} INV_REGION_DESC;
// Itempickup stuff
BOOLEAN InitializeItemPickupMenu( SOLDIERTYPE *pSoldier, INT16 sGridNo, ITEM_POOL *pItemPool, INT16 sScreenX, INT16 sScreenY, INT8 bZLevel );
void RenderItemPickupMenu( );
void RemoveItemPickupMenu( );
void SetItemPickupMenuDirty( BOOLEAN fDirtyLevel );
BOOLEAN HandleItemPickupMenu( );
void SetPickUpMenuDirtyLevel( BOOLEAN fDirtyLevel );
// FUNCTIONS FOR INTERFACEING WITH ITEM PANEL STUFF
void INVRenderINVPanelItem( SOLDIERTYPE *pSoldier, INT16 sPocket, UINT8 fDirtyLevel );
BOOLEAN InitInvSlotInterface( INV_REGION_DESC *pRegionDesc , INV_REGION_DESC *pCamoRegion, MOUSE_CALLBACK INVMoveCallback, MOUSE_CALLBACK INVClickCallback, MOUSE_CALLBACK INVMoveCammoCallback, MOUSE_CALLBACK INVClickCammoCallback, BOOLEAN fSetHighestPrioity );
void ShutdownInvSlotInterface( );
void GetSlotInvXY( UINT8 ubPos, INT16 *psX, INT16 *psY );
void GetSlotInvHeightWidth( UINT8 ubPos, INT16 *psWidth, INT16 *psHeight );
void HandleRenderInvSlots( SOLDIERTYPE *pSoldier, UINT8 fDirtyLevel );
void HandleNewlyAddedItems( SOLDIERTYPE *pSoldier, BOOLEAN *fDirtyLevel );
void RenderInvBodyPanel( SOLDIERTYPE *pSoldier, INT16 sX, INT16 sY );
void DisableInvRegions( BOOLEAN fDisable );
void DegradeNewlyAddedItems( );
void CheckForAnyNewlyAddedItems( SOLDIERTYPE *pSoldier );
BOOLEAN HandleCompatibleAmmoUI( SOLDIERTYPE *pSoldier, INT8 bInvPos, BOOLEAN fOn );
// THIS FUNCTION IS CALLED TO RENDER AN ITEM.
// uiBuffer - The Dest Video Surface - can only be FRAME_BUFFER or guiSAVEBUFFER
// pSoldier - used for determining whether burst mode needs display
// pObject - Usually taken from pSoldier->inv[HANDPOS]
// sX, sY, Width, Height, - Will Center it in the Width
// fDirtyLevel if == DIRTYLEVEL2 will render everything
// if == DIRTYLEVEL1 will render bullets and status only
//
// pubHighlightCounter - if not null, and == 2 - will display name above item
// - if == 1 will only dirty the name space and then set counter to 0
// Last parameter used mainly for when mouse is over item
void INVRenderItem( UINT32 uiBuffer, SOLDIERTYPE * pSoldier, OBJECTTYPE *pObject, INT16 sX, INT16 sY, INT16 sWidth, INT16 sHeight, UINT8 fDirtyLevel, UINT8 *pubHighlightCounter, UINT8 ubStatusIndex, BOOLEAN fOutline, INT16 sOutlineColor );
extern BOOLEAN gfInItemDescBox;
BOOLEAN InItemDescriptionBox( );
BOOLEAN InitItemDescriptionBox( SOLDIERTYPE *pSoldier, UINT8 ubPosition, INT16 sX, INT16 sY, UINT8 ubStatusIndex );
BOOLEAN InternalInitItemDescriptionBox( OBJECTTYPE *pObject, INT16 sX, INT16 sY, UINT8 ubStatusIndex, SOLDIERTYPE *pSoldier );
BOOLEAN InitKeyItemDescriptionBox( SOLDIERTYPE *pSoldier, UINT8 ubPosition, INT16 sX, INT16 sY, UINT8 ubStatusIndex );
void RenderItemDescriptionBox( );
void HandleItemDescriptionBox( BOOLEAN *pfDirty );
void DeleteItemDescriptionBox( );
BOOLEAN InItemStackPopup( );
BOOLEAN InitItemStackPopup( SOLDIERTYPE *pSoldier, UINT8 ubPosition, INT16 sInvX, INT16 sInvY, INT16 sInvWidth, INT16 sInvHeight );
void RenderItemStackPopup( BOOLEAN fFullRender );
void HandleItemStackPopup( );
void DeleteItemStackPopup( );
void EndItemStackPopupWithItemInHand( );
// keyring handlers
BOOLEAN InitKeyRingPopup( SOLDIERTYPE *pSoldier, INT16 sInvX, INT16 sInvY, INT16 sInvWidth, INT16 sInvHeight );
void RenderKeyRingPopup( BOOLEAN fFullRender );
void InitKeyRingInterface( MOUSE_CALLBACK KeyRingClickCallback );
void InitMapKeyRingInterface( MOUSE_CALLBACK KeyRingClickCallback );
void DeleteKeyRingPopup( );
void ShutdownKeyRingInterface( void );
BOOLEAN InKeyRingPopup( void );
void BeginKeyRingItemPointer( SOLDIERTYPE *pSoldier, UINT8 ubKeyRingPosition );
extern OBJECTTYPE *gpItemPointer;
extern OBJECTTYPE gItemPointer;
extern SOLDIERTYPE *gpItemPointerSoldier;
extern UINT16 usItemSnapCursor;
extern UINT16 us16BPPItemCyclePlacedItemColors[ 20 ];
extern BOOLEAN gfItemPointerDifferentThanDefault;
void BeginItemPointer( SOLDIERTYPE *pSoldier, UINT8 ubHandPos );
void InternalBeginItemPointer( SOLDIERTYPE *pSoldier, OBJECTTYPE *pObject, INT8 bHandPos );
void EndItemPointer( );
void DrawItemFreeCursor( );
void DrawItemTileCursor( );
void HideItemTileCursor( );
void InitItemInterface( );
BOOLEAN ItemCursorInLobRange( UINT16 usMapPos );
BOOLEAN HandleItemPointerClick( UINT16 usMapPos );
UINT32 GetInterfaceGraphicForItem( INVTYPE *pItem );
UINT16 GetTileGraphicForItem( INVTYPE *pItem );
BOOLEAN LoadTileGraphicForItem( INVTYPE *pItem, UINT32 *puiVo );
void GetHelpTextForItem( INT16 * pzStr, OBJECTTYPE *pObject, SOLDIERTYPE *pSoldier );
BOOLEAN AttemptToApplyCamo( SOLDIERTYPE *pSoldier, UINT16 usItemIndex );
UINT8 GetPrefferedItemSlotGraphicNum( UINT16 usItem );
void CancelItemPointer( );
BOOLEAN LoadItemCursorFromSavedGame( HWFILE hFile );
BOOLEAN SaveItemCursorToSavedGame( HWFILE hFile );
void EnableKeyRing( BOOLEAN fEnable );
// handle compatable items for merc and map inventory
BOOLEAN HandleCompatibleAmmoUIForMapScreen( SOLDIERTYPE *pSoldier, INT32 bInvPos, BOOLEAN fOn, BOOLEAN fFromMerc );
BOOLEAN HandleCompatibleAmmoUIForMapInventory( SOLDIERTYPE *pSoldier, INT32 bInvPos, INT32 iStartSlotNumber, BOOLEAN fOn, BOOLEAN fFromMerc );
void ResetCompatibleItemArray( );
void CycleItemDescriptionItem( );
BOOLEAN InitializeStealItemPickupMenu( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, ITEM_POOL *pItemPool, UINT8 ubCount);
#endif
File diff suppressed because it is too large Load Diff
+138
View File
@@ -0,0 +1,138 @@
#ifndef __INTERFACE_PANELS
#define __INTERFACE_PANELS
typedef enum
{
STANCEUP_BUTTON = 0,
UPDOWN_BUTTON,
CLIMB_BUTTON,
STANCEDOWN_BUTTON,
HANDCURSOR_BUTTON,
PREVMERC_BUTTON,
NEXTMERC_BUTTON,
OPTIONS_BUTTON,
BURSTMODE_BUTTON,
LOOK_BUTTON,
TALK_BUTTON,
MUTE_BUTTON,
SM_DONE_BUTTON,
SM_MAP_SCREEN_BUTTON,
NUM_SM_BUTTONS
};
typedef enum
{
TEAM_DONE_BUTTON = 0,
TEAM_MAP_SCREEN_BUTTON,
CHANGE_SQUAD_BUTTON,
NUM_TEAM_BUTTONS
};
#define NEW_ITEM_CYCLE_COUNT 19
#define NEW_ITEM_CYCLES 4
#define NUM_TEAM_SLOTS 6
#define PASSING_ITEM_DISTANCE_OKLIFE 3
#define PASSING_ITEM_DISTANCE_NOTOKLIFE 2
#define SHOW_LOCATOR_NORMAL 1
#define SHOW_LOCATOR_FAST 2
BOOLEAN CreateSMPanelButtons( );
void RemoveSMPanelButtons( );
BOOLEAN InitializeSMPanel( );
BOOLEAN ShutdownSMPanel( );
void RenderSMPanel( BOOLEAN *pfDirty );
void EnableSMPanelButtons( BOOLEAN fEnable, BOOLEAN fFromItemPickup );
/* In this function i will initialize all coords for SingleMercPanel
* If i will success i will return true, i think that could be usefull when
* we will have our panes more customizable for ex. we can read coords from file
* and when we will read all values we return TRUE if not we will retunf FALSE
* any questions? joker
*/
BOOLEAN InitializeSMPanelCoords( );
BOOLEAN CreateTEAMPanelButtons( );
void RemoveTEAMPanelButtons( );
BOOLEAN InitializeTEAMPanel( );
BOOLEAN ShutdownTEAMPanel( );
void RenderTEAMPanel( BOOLEAN fDirty );
void UpdateTEAMPanel( );
/*
* Just like b4 we will initialize all coords but now for TEAMPanel
*/
BOOLEAN InitializeTEAMPanelCoords( );
void SetSMPanelCurrentMerc( UINT8 ubNewID );
void SetTEAMPanelCurrentMerc( UINT8 ubNewID );
UINT16 GetSMPanelCurrentMerc( );
void UpdateSMPanel( );
BOOLEAN InitTEAMSlots( );
void AddPlayerToInterfaceTeamSlot( UINT8 ubID );
BOOLEAN RemovePlayerFromInterfaceTeamSlot( UINT8 ubID );
BOOLEAN GetPlayerIDFromInterfaceTeamSlot( UINT8 ubPanelSlot, UINT8 *pubID );
void RemoveAllPlayersFromSlot( );
BOOLEAN PlayerExistsInSlot( UINT8 ubID );
BOOLEAN RemovePlayerFromTeamSlotGivenMercID( UINT8 ubMercID );
void CheckForAndAddMercToTeamPanel( SOLDIERTYPE *pSoldier );
void DisableTacticalTeamPanelButtons( BOOLEAN fDisable );
void RenderTownIDString( );
void KeyRingSlotInvClickCallback( MOUSE_REGION * pRegion, INT32 iReason );
// ATE TO BE MOVED TO INTERFACE_ITEMS.C
extern INT8 gbNewItem[ NUM_INV_SLOTS ];
extern INT8 gbNewItemCycle[ NUM_INV_SLOTS ];
extern UINT8 gubNewItemMerc;
void ShowRadioLocator( UINT8 ubID, UINT8 ubLocatorSpeed );
void EndRadioLocator( UINT8 ubID );
extern MOUSE_REGION gSMPanelRegion;
extern UINT32 guiSecItemHiddenVO;
extern BOOLEAN gfDisableTacticalPanelButtons;
typedef struct
{
UINT8 ubID;
BOOLEAN fOccupied;
} TEAM_PANEL_SLOTS_TYPE;
extern TEAM_PANEL_SLOTS_TYPE gTeamPanel[ NUM_TEAM_SLOTS ];
//Used when the shop keeper interface is active
void DisableSMPpanelButtonsWhenInShopKeeperInterface( BOOLEAN fDontDrawButtons );
//void DisableSMPpanelButtonsWhenInShopKeeperInterface( );
//
void ReEvaluateDisabledINVPanelButtons( );
void CheckForReEvaluateDisabledINVPanelButtons( );
void CheckForDisabledForGiveItem( );
void ReevaluateItemHatches( SOLDIERTYPE *pSoldier, BOOLEAN fEnable );
void HandlePanelFaceAnimations( SOLDIERTYPE *pSoldier );
void GoToMapScreenFromTactical( void );
void HandleTacticalEffectsOfEquipmentChange( SOLDIERTYPE *pSoldier, UINT32 uiInvPos, UINT16 usOldItem, UINT16 usNewItem );
void FinishAnySkullPanelAnimations( );
UINT8 FindNextMercInTeamPanel( SOLDIERTYPE *pSoldier, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs );
#endif
+495
View File
@@ -0,0 +1,495 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include <stdio.h>
#include <stdarg.h>
#include "sgp.h"
#include "himage.h"
#include "vobject.h"
#include "interface utils.h"
#include "render dirty.h"
#include "interface.h"
#include "interface control.h"
#include "sysutil.h"
#include "faces.h"
#include "render dirty.h"
#include "weapons.h"
#include "Overhead.h"
#include "Soldier macros.h"
#include "line.h"
#endif
#define LIFE_BAR_SHADOW FROMRGB( 108, 12, 12 )
#define LIFE_BAR FROMRGB( 200, 0, 0 )
#define BANDAGE_BAR_SHADOW FROMRGB( 156, 60, 60 )
#define BANDAGE_BAR FROMRGB( 222, 132, 132 )
#define BLEEDING_BAR_SHADOW FROMRGB( 128, 128, 60 )
#define BLEEDING_BAR FROMRGB( 240, 240, 20 )
#define CURR_BREATH_BAR_SHADOW FROMRGB( 8, 12, 118 ) // the MAX max breatth, always at 100%
#define CURR_BREATH_BAR FROMRGB( 8, 12, 160 )
#define CURR_MAX_BREATH FROMRGB( 0, 0, 0 ) // the current max breath, black
#define CURR_MAX_BREATH_SHADOW FROMRGB( 0, 0, 0 )
#define MORALE_BAR_SHADOW FROMRGB( 8, 112, 12 )
#define MORALE_BAR FROMRGB( 8, 180, 12 )
#define BREATH_BAR_SHADOW FROMRGB( 60, 108, 108 ) // the lt blue current breath
#define BREATH_BAR FROMRGB( 113, 178, 218 )
#define BREATH_BAR_SHAD_BACK FROMRGB( 1,1,1 )
#define FACE_WIDTH 48
#define FACE_HEIGHT 43
// backgrounds for breath max background
extern UINT32 guiBrownBackgroundForTeamPanel;
extern UINT32 guiGoldBackgroundForTeamPanel;
// selected grunt
extern UINT16 gusSelectedSoldier;
// car portraits
enum{
ELDORADO_PORTRAIT =0,
HUMMER_PORTRAIT,
ICE_CREAM_TRUCT_PORTRAIT,
JEEP_PORTRAIT,
NUMBER_CAR_PORTRAITS,
};
// the ids for the car portraits
INT32 giCarPortraits[ 4 ] = { -1, -1, -1, -1 };
// the car portrait file names
STR pbCarPortraitFileNames[ ]={
"INTERFACE\\eldorado.sti",
"INTERFACE\\Hummer.sti",
"INTERFACE\\ice Cream Truck.sti",
"INTERFACE\\Jeep.sti",
};
// load int he portraits for the car faces that will be use in mapscreen
BOOLEAN LoadCarPortraitValues( void )
{
INT32 iCounter = 0;
VOBJECT_DESC VObjectDesc;
if( giCarPortraits[ 0 ] != -1 )
{
return FALSE;
}
for( iCounter = 0; iCounter < NUMBER_CAR_PORTRAITS; iCounter++ )
{
VObjectDesc.fCreateFlags = VOBJECT_CREATE_FROMFILE;
sprintf( VObjectDesc.ImageFile, pbCarPortraitFileNames[ iCounter ] );
CHECKF( AddVideoObject( &VObjectDesc, (UINT32 *)&giCarPortraits[ iCounter ] ) );
}
return( TRUE );
}
// get rid of the images we loaded for the mapscreen car portraits
void UnLoadCarPortraits( void )
{
INT32 iCounter = 0;
// car protraits loaded?
if( giCarPortraits[ 0 ] == -1 )
{
return;
}
for( iCounter = 0; iCounter < NUMBER_CAR_PORTRAITS; iCounter++ )
{
DeleteVideoObjectFromIndex( giCarPortraits[ iCounter ] );
giCarPortraits[ iCounter ] = -1;
}
return;
}
void DrawLifeUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, BOOLEAN fErase, UINT32 uiBuffer )
{
FLOAT dStart, dEnd, dPercentage;
//UINT16 usLineColor;
UINT32 uiDestPitchBYTES;
UINT8 *pDestBuf;
UINT16 usLineColor;
INT8 bBandage;
// Erase what was there
if( fErase )
{
RestoreExternBackgroundRect( sXPos, (INT16)(sYPos - sHeight), sWidth, (INT16)(sHeight + 1 ) );
}
if( pSoldier->bLife == 0 )
{
// are they dead?
return;
}
pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
// FIRST DO MAX LIFE
dPercentage = (FLOAT)pSoldier->bLife / (FLOAT)100;
dEnd = dPercentage * sHeight;
dStart = sYPos;
usLineColor = Get16BPPColor( LIFE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( LIFE_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( LIFE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
// NOW DO BANDAGE
// Calculate bandage
bBandage = pSoldier->bLifeMax - pSoldier->bLife - pSoldier->bBleeding;
if ( bBandage )
{
dPercentage = (FLOAT)bBandage / (FLOAT)100;
dStart = (FLOAT)( sYPos - dEnd );
dEnd = ( dPercentage * sHeight );
usLineColor = Get16BPPColor( BANDAGE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( BANDAGE_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( BANDAGE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
}
// NOW DO BLEEDING
if ( pSoldier->bBleeding )
{
dPercentage = (FLOAT)pSoldier->bBleeding / (FLOAT)100;
dStart = (FLOAT)( dStart - dEnd );
dEnd = ( dPercentage * sHeight );
usLineColor = Get16BPPColor( BLEEDING_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( BLEEDING_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( BLEEDING_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
}
UnLockVideoSurface( uiBuffer );
}
void DrawBreathUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, BOOLEAN fErase, UINT32 uiBuffer )
{
FLOAT dStart, dEnd, dPercentage;
//UINT16 usLineColor;
UINT32 uiDestPitchBYTES;
UINT8 *pDestBuf;
UINT16 usLineColor;
HVOBJECT hHandle;
// Erase what was there
if ( fErase )
{
RestoreExternBackgroundRect( sXPos, (INT16)(sYPos - sHeight), sWidth, (INT16)(sHeight + 1 ) );
}
if( pSoldier->bLife == 0 )
{
// are they dead?
return;
}
// DO MAX MAX BREATH
dPercentage = 1.;
dEnd = dPercentage * sHeight;
dStart = sYPos;
// brown guy
GetVideoObject( &hHandle, guiBrownBackgroundForTeamPanel );
// DO MAX BREATH
if( guiCurrentScreen != MAP_SCREEN )
{
if( gusSelectedSoldier == pSoldier->ubID && gTacticalStatus.ubCurrentTeam == OUR_TEAM && OK_INTERRUPT_MERC( pSoldier ) )
{
// gold, the second entry in the .sti
BltVideoObject( uiBuffer , hHandle, 1, sXPos, ( INT16 )( sYPos - sHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
}
else
{
// brown, first entry
BltVideoObject( uiBuffer , hHandle, 0, sXPos, ( INT16 )( sYPos - sHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
}
}
else
{
// brown, first entry
BltVideoObject( uiBuffer , hHandle, 0, sXPos, ( INT16 )( sYPos - sHeight ), VO_BLT_SRCTRANSPARENCY, NULL );
}
pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
if( pSoldier->bBreathMax <= 97 )
{
dPercentage = (FLOAT)( ( pSoldier->bBreathMax + 3 ) )/ (FLOAT)100;
dEnd = dPercentage * sHeight;
dStart = sYPos;
// the old background colors for breath max diff
usLineColor = Get16BPPColor( BREATH_BAR_SHAD_BACK );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( BREATH_BAR_SHAD_BACK );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( BREATH_BAR_SHAD_BACK );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
}
dPercentage = (FLOAT)pSoldier->bBreathMax / (FLOAT)100;
dEnd = dPercentage * sHeight;
dStart = sYPos;
usLineColor = Get16BPPColor( CURR_MAX_BREATH_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( CURR_MAX_BREATH );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( CURR_MAX_BREATH_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
// NOW DO BREATH
dPercentage = (FLOAT)pSoldier->bBreath / (FLOAT)100;
dEnd = dPercentage * sHeight;
dStart = sYPos;
usLineColor = Get16BPPColor( CURR_BREATH_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( CURR_BREATH_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( CURR_BREATH_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
UnLockVideoSurface( uiBuffer );
}
void DrawMoraleUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, BOOLEAN fErase, UINT32 uiBuffer )
{
FLOAT dStart, dEnd, dPercentage;
//UINT16 usLineColor;
UINT32 uiDestPitchBYTES;
UINT8 *pDestBuf;
UINT16 usLineColor;
// Erase what was there
if ( fErase )
{
RestoreExternBackgroundRect( sXPos, (INT16)(sYPos - sHeight), sWidth, (INT16)(sHeight + 1 ) );
}
if( pSoldier->bLife == 0 )
{
// are they dead?
return;
}
pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
// FIRST DO BREATH
dPercentage = (FLOAT)pSoldier->bMorale / (FLOAT)100;
dEnd = dPercentage * sHeight;
dStart = sYPos;
usLineColor = Get16BPPColor( MORALE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = Get16BPPColor( MORALE_BAR );
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
usLineColor = Get16BPPColor( MORALE_BAR_SHADOW );
RectangleDraw( TRUE, sXPos+ 2, (INT32)dStart, sXPos + 2, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
UnLockVideoSurface( uiBuffer );
}
void DrawItemUIBarEx( OBJECTTYPE *pObject, UINT8 ubStatus, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, INT16 sColor1, INT16 sColor2, BOOLEAN fErase, UINT32 uiBuffer )
{
FLOAT dStart, dEnd, dPercentage;
//UINT16 usLineColor;
UINT32 uiDestPitchBYTES;
UINT8 *pDestBuf;
UINT16 usLineColor;
INT16 sValue;
if ( ubStatus >= DRAW_ITEM_STATUS_ATTACHMENT1 )
{
sValue = pObject->bAttachStatus[ ubStatus - DRAW_ITEM_STATUS_ATTACHMENT1 ];
}
else
{
sValue = pObject->bStatus[ ubStatus ];
}
// Adjust for ammo, other thingys..
if( Item[ pObject->usItem ].usItemClass & IC_AMMO )
{
sValue = sValue * 100 / Magazine[ Item[ pObject->usItem ].ubClassIndex ].ubMagSize;
if ( sValue < 0 )
{
sValue = pObject->ubShotsLeft[0] * 100 / Magazine[ Item[ pObject->usItem ].ubClassIndex ].ubMagSize;
DebugMsg ( TOPIC_JA2, DBG_LEVEL_3, String("Ammo status: shots left %d * 100 / Mag Size %d = value %d",pObject->ubShotsLeft[0],Magazine[ Item[ pObject->usItem ].ubClassIndex ].ubMagSize,sValue ));
}
if ( sValue > 100 )
{
sValue = 100;
}
}
if( Item[ pObject->usItem ].usItemClass & IC_KEY )
{
sValue =100;
}
// ATE: Subtract 1 to exagerate bad status
if ( sValue < 100 && sValue > 1 )
{
sValue--;
}
// Erase what was there
if ( fErase )
{
//RestoreExternBackgroundRect( sXPos, (INT16)(sYPos - sHeight), sWidth, (INT16)(sHeight + 1 ) );
}
pDestBuf = LockVideoSurface( uiBuffer, &uiDestPitchBYTES );
SetClippingRegionAndImageWidth( uiDestPitchBYTES, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT );
// FIRST DO BREATH
dPercentage = (FLOAT)sValue / (FLOAT)100;
dEnd = dPercentage * sHeight;
dStart = sYPos;
//usLineColor = Get16BPPColor( STATUS_BAR );
usLineColor = sColor1;
RectangleDraw( TRUE, sXPos, (INT32)dStart, sXPos, (INT32)( dStart - dEnd ) , usLineColor, pDestBuf );
usLineColor = sColor2;
RectangleDraw( TRUE, sXPos+ 1, (INT32)dStart, sXPos + 1, (INT32)( dStart - dEnd ), usLineColor, pDestBuf );
UnLockVideoSurface( uiBuffer );
if ( uiBuffer == guiSAVEBUFFER )
{
RestoreExternBackgroundRect( sXPos, (INT16)(sYPos - sHeight), sWidth, (INT16)(sHeight + 1 ) );
}
else
{
InvalidateRegion( sXPos, (INT16)(sYPos - sHeight), sXPos + sWidth, (INT16)(sYPos + 1 ) );
}
}
void RenderSoldierFace( SOLDIERTYPE *pSoldier, INT16 sFaceX, INT16 sFaceY, BOOLEAN fAutoFace )
{
BOOLEAN fDoFace = FALSE;
INT32 iFaceIndex = -1;
UINT8 ubVehicleType = 0;
if ( pSoldier->bActive )
{
if( pSoldier->uiStatusFlags & SOLDIER_VEHICLE )
{
// get the type of vehicle
ubVehicleType = pVehicleList[ pSoldier->bVehicleID ].ubVehicleType;
// just draw the vehicle
BltVideoObjectFromIndex( guiSAVEBUFFER, giCarPortraits[ ubVehicleType ], 0, sFaceX, sFaceY, VO_BLT_SRCTRANSPARENCY, NULL );
RestoreExternBackgroundRect( sFaceX, sFaceY, FACE_WIDTH, FACE_HEIGHT );
return;
}
if ( fAutoFace )
{
// OK, check if this face actually went active...
if ( gFacesData[ pSoldier->iFaceIndex ].uiFlags & FACE_INACTIVE_HANDLED_ELSEWHERE )
{
// Render as an extern face...
fAutoFace = FALSE;
}
else
{
SetAutoFaceActiveFromSoldier( FRAME_BUFFER, guiSAVEBUFFER, pSoldier->ubID , sFaceX, sFaceY );
// SetAutoFaceActiveFromSoldier( FRAME_BUFFER, FACE_AUTO_RESTORE_BUFFER, pSoldier->ubID , sFaceX, sFaceY );
}
}
fDoFace = TRUE;
if ( fDoFace )
{
if ( fAutoFace )
{
RenderAutoFaceFromSoldier( pSoldier->ubID );
}
else
{
ExternRenderFaceFromSoldier( guiSAVEBUFFER, pSoldier->ubID, sFaceX, sFaceY );
}
}
}
else
{
// Put close panel there
//if(gbPixelDepth==16)
//{
BltVideoObjectFromIndex( guiSAVEBUFFER, guiCLOSE, 5, sFaceX, sFaceY, VO_BLT_SRCTRANSPARENCY, NULL );
//}
RestoreExternBackgroundRect( sFaceX, sFaceY, FACE_WIDTH, FACE_HEIGHT );
}
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef __INTERFACE_UTILS_H
#define __INTERFACE_UTILS_H
#include "Soldier Control.h"
#define DRAW_ITEM_STATUS_ATTACHMENT1 200
#define DRAW_ITEM_STATUS_ATTACHMENT2 201
#define DRAW_ITEM_STATUS_ATTACHMENT3 202
#define DRAW_ITEM_STATUS_ATTACHMENT4 203
void DrawMoraleUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, BOOLEAN fErase, UINT32 uiBuffer );
void DrawBreathUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, BOOLEAN fErase, UINT32 uiBuffer );
void DrawLifeUIBarEx( SOLDIERTYPE *pSoldier, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, BOOLEAN fErase, UINT32 uiBuffer );
void DrawItemUIBarEx( OBJECTTYPE *pObject, UINT8 ubStatus, INT16 sXPos, INT16 sYPos, INT16 sWidth, INT16 sHeight, INT16 sColor1, INT16 sColor2, BOOLEAN fErase, UINT32 uiBuffer );
void RenderSoldierFace( SOLDIERTYPE *pSoldier, INT16 sFaceX, INT16 sFaceY, BOOLEAN fAutoFace );
// load portraits for cars
BOOLEAN LoadCarPortraitValues( void );
// get rid of the loaded portraits for cars
void UnLoadCarPortraits( void );
#endif
File diff suppressed because it is too large Load Diff
+246
View File
@@ -0,0 +1,246 @@
#ifndef _INTERFACE_H
#define _INTERFACE_H
#include "handle UI.h"
#include "mousesystem.h"
#include "structure.h"
#define MAX_UICOMPOSITES 4
extern int INTERFACE_WIDTH; // 640
extern int INTERFACE_HEIGHT; // 120
extern int INV_INTERFACE_HEIGHT; // 140
extern int INTERFACE_START_X;
extern int INTERFACE_START_Y; // ( SCREEN_HEIGHT - INTERFACE_HEIGHT )
extern int INV_INTERFACE_START_Y; // ( SCREEN_HEIGHT - INV_INTERFACE_HEIGHT )
// FLASH PORTRAIT CODES
#define FLASH_PORTRAIT_STOP 0
#define FLASH_PORTRAIT_START 1
#define FLASH_PORTRAIT_WAITING 2
#define FLASH_PORTRAIT_DELAY 150
// FLASH PORTRAIT PALETTE IDS
#define FLASH_PORTRAIT_NOSHADE 0
#define FLASH_PORTRAIT_STARTSHADE 1
#define FLASH_PORTRAIT_ENDSHADE 2
#define FLASH_PORTRAIT_DARKSHADE 3
#define FLASH_PORTRAIT_GRAYSHADE 4
#define FLASH_PORTRAIT_LITESHADE 5
// GLOBAL DEFINES FOR SOME UI FLAGS
#define ARROWS_HIDE_UP 0x00000002
#define ARROWS_HIDE_DOWN 0x00000004
#define ARROWS_SHOW_UP_BESIDE 0x00000008
#define ARROWS_SHOW_DOWN_BESIDE 0x00000020
#define ARROWS_SHOW_UP_ABOVE_Y 0x00000040
#define ARROWS_SHOW_DOWN_BELOW_Y 0x00000080
#define ARROWS_SHOW_DOWN_BELOW_G 0x00000200
#define ARROWS_SHOW_DOWN_BELOW_YG 0x00000400
#define ARROWS_SHOW_DOWN_BELOW_GG 0x00000800
#define ARROWS_SHOW_UP_ABOVE_G 0x00002000
#define ARROWS_SHOW_UP_ABOVE_YG 0x00004000
#define ARROWS_SHOW_UP_ABOVE_GG 0x00008000
#define ARROWS_SHOW_UP_ABOVE_YY 0x00020000
#define ARROWS_SHOW_DOWN_BELOW_YY 0x00040000
#define ARROWS_SHOW_UP_ABOVE_CLIMB 0x00080000
#define ARROWS_SHOW_UP_ABOVE_CLIMB2 0x00400000
#define ARROWS_SHOW_UP_ABOVE_CLIMB3 0x00800000
#define ARROWS_SHOW_DOWN_CLIMB 0x02000000
#define ROOF_LEVEL_HEIGHT 50
#define LOCATEANDSELECT_MERC 1
#define LOCATE_MERC_ONCE 2
// Interface level enums
enum
{
I_GROUND_LEVEL,
I_ROOF_LEVEL,
I_NUMLEVELS
};
#define DRAW_RED_BAR 1
#define DRAW_BLUE_BAR 2
#define DRAW_ERASE_BAR 3
extern BOOLEAN gfSwitchPanel;
extern BOOLEAN gfUIStanceDifferent;
extern UINT8 gbNewPanel;
extern UINT8 gubNewPanelParam;
extern INT16 gsCurInterfacePanel;
extern UINT32 guiRENDERBUFFER;
extern UINT32 guiCLOSE;
extern UINT32 guiDEAD;
extern UINT32 guiHATCH;
extern UINT32 guiINTEXT;
extern UINT32 guiGUNSM;
extern UINT32 guiP1ITEMS;
extern UINT32 guiP2ITEMS;
extern UINT32 guiP3ITEMS;
extern UINT32 guiCOMPANEL;
extern UINT32 guiCOMPANELB;
extern UINT32 guiRADIO;
extern UINT32 guiPORTRAITICONS;
extern UINT32 guiBURSTACCUM;
extern UINT32 guiITEMPOINTERHATCHES;
extern MOUSE_REGION gViewportRegion;
extern MOUSE_REGION gRadarRegion;
extern MOUSE_REGION gBottomPanalRegion;
#define MOVEMENT_MENU_LOOK 1
#define MOVEMENT_MENU_ACTIONC 2
#define MOVEMENT_MENU_HAND 3
#define MOVEMENT_MENU_TALK 4
#define MOVEMENT_MENU_RUN 5
#define MOVEMENT_MENU_WALK 6
#define MOVEMENT_MENU_SWAT 7
#define MOVEMENT_MENU_PRONE 8
#define DIRTYLEVEL0 0
#define DIRTYLEVEL1 1
#define DIRTYLEVEL2 2
typedef enum
{
SM_PANEL,
TEAM_PANEL,
NUM_UI_PANELS
} InterfacePanelDefines;
BOOLEAN InitializeTacticalInterface( );
BOOLEAN ShutdownTacticalInterface( );
extern BOOLEAN fInterfacePanelDirty;
extern BOOLEAN gfPausedTacticalRenderFlags;
extern BOOLEAN gfPausedTacticalRenderInterfaceFlags;
extern INT16 gsInterfaceLevel;
extern BOOLEAN gfInMovementMenu;
void PopupPositionMenu( UI_EVENT *pUIEvent );
void PopDownPositionMenu( );
void PopupMovementMenu( UI_EVENT *pUIEvent );
void PopDownMovementMenu( );
void RenderMovementMenu( );
void CancelMovementMenu( );
void PopDownOpenDoorMenu( );
void RenderOpenDoorMenu( );
BOOLEAN InitDoorOpenMenu( SOLDIERTYPE *pSoldier, STRUCTURE *pStructure, UINT8 ubDirection, BOOLEAN fClosingDoor );
BOOLEAN HandleOpenDoorMenu( );
void CancelOpenDoorMenu( );
void HandleInterfaceBackgrounds( );
void BeginOverlayMessage( UINT32 uiFont, UINT16 *pFontString, ... );
void EndOverlayMessage( );
void DrawSelectedUIAboveGuy( UINT16 usSoldierID );
void CreateCurrentTacticalPanelButtons( );
void RemoveCurrentTacticalPanelButtons( );
void SetCurrentTacticalPanelCurrentMerc( UINT8 ubID );
void SetCurrentInterfacePanel( UINT8 ubNewPanel );
BOOLEAN IsMercPortraitVisible( UINT8 ubSoldierID );
BOOLEAN InitializeCurrentPanel( );
void ShutdownCurrentPanel( );
void ClearInterface( );
void RestoreInterface( );
void RenderArrows( );
void EraseRenderArrows( );
void GetArrowsBackground( );
void HandleUpDownArrowBackgrounds( );
void EndDeadlockMsg( );
void HandleLocateSelectMerc( UINT8 ubID, INT8 bFlag );
void DirtyMercPanelInterface( SOLDIERTYPE *pSoldier, UINT8 ubDirtyLevel );
void EndUIMessage( );
void BeginUIMessage( UINT16 *pFontString, ... );
void InternalBeginUIMessage( BOOLEAN fUseSkullIcon, UINT16 *pFontString, ... );
// map screen version, for centering over the map area
void BeginMapUIMessage( UINT8 fPosition, UINT16 *pFontString, ... );
extern UINT16 gusUIOldSelectedSoldier;
extern INT32 giUIMessageOverlay;
extern UINT32 guiUIMessageTime;
enum MESSAGE_TYPES
{
NO_MESSAGE,
COMPUTER_TURN_MESSAGE,
COMPUTER_INTERRUPT_MESSAGE,
PLAYER_INTERRUPT_MESSAGE,
MILITIA_INTERRUPT_MESSAGE,
AIR_RAID_TURN_MESSAGE,
PLAYER_TURN_MESSAGE,
} ;
void HandleTopMessages( );
BOOLEAN AddTopMessage( UINT8 ubType, UINT16 * pzString );
BOOLEAN InTopMessageBarAnimation( );
void EndTopMessage( );
void PauseRT( BOOLEAN fPause );
void InitEnemyUIBar( UINT8 ubNumEnemies, UINT8 ubDoneEnemies );
UINT16 *GetSoldierHealthString( SOLDIERTYPE *pSoldier );
void GetLaunchItemParamsFromUI( );
void RenderAimCubeUI( );
void ResetAimCubeAI( );
void SetupAimCubeAI( );
void IncrementAimCubeUI( );
void EndAimCubeUI( );
void BeginAimCubeUI( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 ubLevel, UINT8 bStartPower, INT8 bStartHeight );
BOOLEAN AimCubeUIClick( );
void ResetPhysicsTrajectoryUI( );
void SetupPhysicsTrajectoryUI( );
void EndPhysicsTrajectoryUI( );
void BeginPhysicsTrajectoryUI( INT16 sGridNo, INT8 bLevel, BOOLEAN fBadCTGT );
void InitPlayerUIBar( BOOLEAN fInterrupt );
void ToggleTacticalPanels( );
void DirtyTopMessage( );
void BeginMultiPurposeLocator( INT16 sGridNo, INT8 bLevel, BOOLEAN fSlideTo );
void HandleMultiPurposeLocator( );
void RenderTopmostMultiPurposeLocator( );
#endif
File diff suppressed because it is too large Load Diff
+118
View File
@@ -0,0 +1,118 @@
#ifndef __INVENTORY_CHOOSING_H
#define __INVENTORY_CHOOSING_H
#include "types.h"
#include "Soldier Create.h"
#include "Strategic Status.h"
#define MORTAR_GRENADE_CLASS 100
#define RPG_GRENADE_CLASS 101
typedef struct ARMY_GUN_CHOICE_TYPE
{
UINT8 ubChoices; // how many valid choices there are in this category
INT16 bItemNo[50]; // room for up to 50 choices of gun in each category
UINT32 uiIndex;
} ARMY_GUN_CHOICE_TYPE;
enum
{
//administrator ratings (1-5)
BAD_ADMINISTRATOR_EQUIPMENT_RATING = 1,
POOR_ADMINISTRATOR_EQUIPMENT_RATING,
AVERAGE_ADMINISTRATOR_EQUIPMENT_RATING,
GOOD_ADMINISTRATOR_EQUIPMENT_RATING,
GREAT_ADMINISTRATOR_EQUIPMENT_RATING,
//army ratings (3-7)
BAD_ARMY_EQUIPMENT_RATING = AVERAGE_ADMINISTRATOR_EQUIPMENT_RATING,
POOR_ARMY_EQUIPMENT_RATING,
AVERAGE_ARMY_EQUIPMENT_RATING,
GOOD_ARMY_EQUIPMENT_RATING,
GREAT_ARMY_EQUIPMENT_RATING,
//elite ratings (5-9)
BAD_ELITE_EQUIPMENT_RATING = AVERAGE_ARMY_EQUIPMENT_RATING,
POOR_ELITE_EQUIPMENT_RATING,
AVERAGE_ELITE_EQUIPMENT_RATING,
GOOD_ELITE_EQUIPMENT_RATING,
GREAT_ELITE_EQUIPMENT_RATING,
// militia ratings (1-5)
BAD_MILITIA_EQUIPMENT_RATING = BAD_ADMINISTRATOR_EQUIPMENT_RATING,
POOR_MILITIA_EQUIPMENT_RATING,
AVERAGE_MILITIA_EQUIPMENT_RATING,
GOOD_MILITIA_EQUIPMENT_RATING,
GREAT_MILITIA_EQUIPMENT_RATING,
};
#define MIN_EQUIPMENT_CLASS 1
#define MAX_EQUIPMENT_CLASS 11
// Selects at the start of the game the set of guns the Queen's army will use during this game
void InitArmyGunTypes(void);
//Chooses equipment based on the equipment level (1-11) with best being 11. It allocates a range
//of equipment to choose from.
void GenerateRandomEquipment( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass, INT8 bEquipmentRating);
void ChooseWeaponForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bWeaponClass,
INT8 bAmmoClips, INT8 bAttachClass, BOOLEAN fAttachment );
void ChooseGrenadesForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bGrenades, INT8 bGrenadeClass, BOOLEAN fGrenadeLauncher );
void ChooseArmourForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bHelmetClass,
INT8 bArmourClass, INT8 bLeggingsClass );
void ChooseSpecialWeaponsForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, INT8 bKnifeClass,
BOOLEAN fGrenadeLauncher, BOOLEAN fLAW, BOOLEAN fMortar, BOOLEAN fRPG );
void ChooseFaceGearForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp );
void ChooseLocationSpecificGearForSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp );
BOOLEAN PlaceObjectInSoldierCreateStruct( SOLDIERCREATE_STRUCT *pp, OBJECTTYPE *pObject );
void AssignCreatureInventory( SOLDIERTYPE *pSoldier );
void ReplaceExtendedGuns( SOLDIERCREATE_STRUCT *pp, INT8 bSoldierClass );
UINT16 SelectStandardArmyGun( UINT8 uiGunLevel );
INT8 GetWeaponClass( UINT16 usGun );
void MarkAllWeaponsOfSameGunClassAsDropped( UINT16 usWeapon );
void ResetMortarsOnTeamCount( void );
extern ARMY_GUN_CHOICE_TYPE gExtendedArmyGunChoices[ARMY_GUN_LEVELS];
enum
{
HELMET = 0,
VEST,
LEGS,
GRENADE,
KIT,
BOMB,
MISCITEMS,
GRENADELAUNCHER,
SINGLESHOTROCKETLAUNCHER,
ROCKETLAUNCHER,
MORTARLAUNCHER,
ARMOURATTACHMENT,
GASMASKS,
NVGLOW,
NVGHIGH,
HEARINGAIDS,
SCOPE,
ATTACHMENTS,
KNIVES,
MAX_ITEM_TYPES
};
extern ARMY_GUN_CHOICE_TYPE gArmyItemChoices[MAX_ITEM_TYPES];
#endif
+893
View File
@@ -0,0 +1,893 @@
#ifndef ITEM_TYPES_H
#define ITEM_TYPES_H
#include "types.h"
#define INVALIDCURS 0
#define QUESTCURS 1
#define PUNCHCURS 2
#define TARGETCURS 3
#define KNIFECURS 4
#define AIDCURS 5
#define TOSSCURS 6
#define MINECURS 8
#define LPICKCURS 9
#define MDETECTCURS 10
#define CROWBARCURS 11
#define SURVCAMCURS 12
#define CAMERACURS 13
#define KEYCURS 14
#define SAWCURS 15
#define WIRECUTCURS 16
#define REMOTECURS 17
#define BOMBCURS 18 // ( only calculated, not set item table )
#define REPAIRCURS 19
#define TRAJECTORYCURS 20
#define JARCURS 21
#define TINCANCURS 22
#define REFUELCURS 23
#define CAMERARANGE 10
#define CONDBUL 0
#define COND 0
#define SINGLE 0
#define LIQ 0
#define USAGE 0
#define BUCKS 0
#define ITEM_NOT_FOUND -1
#define USABLE 10 // minimum work% of items to still be usable
#define MAX_OBJECTS_PER_SLOT 8
#define MAX_ATTACHMENTS 4
#define MAX_MONEY_PER_SLOT 20000
typedef enum
{
BOMB_TIMED = 1,
BOMB_REMOTE,
BOMB_PRESSURE,
BOMB_SWITCH
} DetonatorType;
#define FIRST_MAP_PLACED_FREQUENCY 50
#define PANIC_FREQUENCY 127
#define PANIC_FREQUENCY_2 126
#define PANIC_FREQUENCY_3 125
#define OBJECT_UNDROPPABLE 0x01
#define OBJECT_MODIFIED 0x02
#define OBJECT_AI_UNUSABLE 0x04
#define OBJECT_ARMED_BOMB 0x08
#define OBJECT_KNOWN_TO_BE_TRAPPED 0x10
#define OBJECT_DISABLED_BOMB 0x20
#define OBJECT_ALARM_TRIGGER 0x40
#define OBJECT_NO_OVERWRITE 0x80
typedef struct
{
UINT16 usItem;
UINT8 ubNumberOfObjects;
union
{
struct
{
INT8 bGunStatus; // status % of gun
UINT8 ubGunAmmoType; // ammo type, as per weapons.h
UINT8 ubGunShotsLeft; // duh, amount of ammo left
UINT16 usGunAmmoItem; // the item # for the item table
INT8 bGunAmmoStatus; // only for "attached ammo" - grenades, mortar shells
UINT8 ubGunUnused[MAX_OBJECTS_PER_SLOT - 6];
};
struct
{
UINT8 ubShotsLeft[MAX_OBJECTS_PER_SLOT];
};
struct
{
INT8 bStatus[MAX_OBJECTS_PER_SLOT];
};
struct
{
INT8 bMoneyStatus;
UINT32 uiMoneyAmount;
UINT8 ubMoneyUnused[MAX_OBJECTS_PER_SLOT - 5];
};
struct
{ // this is used by placed bombs, switches, and the action item
INT8 bBombStatus; // % status
INT8 bDetonatorType; // timed, remote, or pressure-activated
UINT16 usBombItem; // the usItem of the bomb.
union
{
struct
{
INT8 bDelay; // >=0 values used only
};
struct
{
INT8 bFrequency; // >=0 values used only
};
};
UINT8 ubBombOwner; // side which placed the bomb
UINT8 bActionValue;// this is used by the ACTION_ITEM fake item
union
{
struct
{
UINT8 ubTolerance; // tolerance value for panic triggers
};
struct
{
UINT8 ubLocationID; // location value for remote non-bomb (special!) triggers
};
};
};
struct
{
INT8 bKeyStatus[ 6 ];
UINT8 ubKeyID;
UINT8 ubKeyUnused[1];
};
struct
{
UINT8 ubOwnerProfile;
UINT8 ubOwnerCivGroup;
UINT8 ubOwnershipUnused[6];
};
};
// attached objects
UINT16 usAttachItem[MAX_ATTACHMENTS];
INT8 bAttachStatus[MAX_ATTACHMENTS];
INT8 fFlags;
UINT8 ubMission;
INT8 bTrap; // 1-10 exp_lvl to detect
UINT8 ubImprintID; // ID of merc that item is imprinted on
UINT8 ubWeight;
UINT8 fUsed; // flags for whether the item is used or not
} OBJECTTYPE;
/*
typedef struct
{
UINT8 ubCursor;
INT8 bSoundType;
UINT8 ubGraphicNum;
INT8 bMaxLoad;
UINT8 ubPerPocket;
UINT8 ubCanDamage;
UINT8 ubWaterDamage;
UINT8 ubCanRepair;
UINT8 ubSeeMeter;
UINT8 ubRange;
UINT8 ubMetal;
UINT8 ubSinkable;
UINT16 ubPrice;
UINT8 ubMission;
UINT8 ubCoolness;
} INVTYPE;
*/
// SUBTYPES
#define IC_NONE 0x00000001
#define IC_GUN 0x00000002
#define IC_BLADE 0x00000004
#define IC_THROWING_KNIFE 0x00000008
#define IC_LAUNCHER 0x00000010
#define IC_TENTACLES 0x00000020
#define IC_THROWN 0x00000040
#define IC_PUNCH 0x00000080
#define IC_GRENADE 0x00000100
#define IC_BOMB 0x00000200
#define IC_AMMO 0x00000400
#define IC_ARMOUR 0x00000800
#define IC_MEDKIT 0x00001000
#define IC_KIT 0x00002000
#define IC_APPLIABLE 0x00004000
#define IC_FACE 0x00008000
#define IC_KEY 0x00010000
#define IC_MISC 0x10000000
#define IC_MONEY 0x20000000
// PARENT TYPES
#define IC_WEAPON ( IC_GUN | IC_BLADE | IC_THROWING_KNIFE | IC_LAUNCHER | IC_TENTACLES )
#define IC_EXPLOSV ( IC_GRENADE | IC_BOMB )
#define IC_BOBBY_GUN ( IC_GUN | IC_LAUNCHER )
#define IC_BOBBY_MISC ( IC_GRENADE | IC_BOMB | IC_MISC | IC_MEDKIT | IC_KIT | IC_BLADE | IC_THROWING_KNIFE | IC_PUNCH | IC_FACE )
// replaces candamage
//#define ITEM_DAMAGEABLE 0x0001
//// replaces canrepair
//#define ITEM_REPAIRABLE 0x0002
//// replaces waterdamage
//#define ITEM_WATER_DAMAGES 0x0004
//// replaces metal
//#define ITEM_METAL 0x0008
//// replaces sinkable
//#define ITEM_SINKS 0x0010
//// replaces seemeter
//#define ITEM_SHOW_STATUS 0x0020
//// for attachers/merges, hidden
//#define ITEM_HIDDEN_ADDON 0x0040
//// needs two hands
//#define ITEM_TWO_HANDED 0x0080
//// can't be found for sale
//#define ITEM_NOT_BUYABLE 0x0100
//// item is an attachment for something
//#define ITEM_ATTACHMENT 0x0200
//// item only belongs in the "big gun list"
//#define ITEM_BIGGUNLIST 0x0400
//// item should not be placed via the editor
//#define ITEM_NOT_EDITOR 0x0800
//// item defaults to undroppable
//#define ITEM_DEFAULT_UNDROPPABLE 0x1000
//// item is terrible for throwing
//#define ITEM_UNAERODYNAMIC 0x2000
//// item is electronic for repair (etc) purposes
//#define ITEM_ELECTRONIC 0x4000
//// item is a PERMANENT attachment
//#define ITEM_INSEPARABLE 0x8000
//
//// item flag combinations
//
//#define IF_STANDARD_GUN ITEM_DAMAGEABLE | ITEM_WATER_DAMAGES | ITEM_REPAIRABLE | ITEM_SHOW_STATUS | ITEM_METAL | ITEM_SINKS
//#define IF_TWOHANDED_GUN IF_STANDARD_GUN | ITEM_TWO_HANDED
//#define IF_STANDARD_BLADE ITEM_DAMAGEABLE | ITEM_WATER_DAMAGES | ITEM_REPAIRABLE | ITEM_SHOW_STATUS | ITEM_METAL | ITEM_SINKS
//#define IF_STANDARD_ARMOUR ITEM_DAMAGEABLE | ITEM_REPAIRABLE | ITEM_SHOW_STATUS | ITEM_SINKS
//#define IF_STANDARD_KIT ITEM_DAMAGEABLE | ITEM_SHOW_STATUS | ITEM_SINKS
//#define IF_STANDARD_CLIP ITEM_SINKS | ITEM_METAL
//#define EXPLOSIVE_GUN( x ) ( x == ROCKET_LAUNCHER || x == TANK_CANNON || x == RPG7 )
typedef struct
{
UINT32 usItemClass;
UINT16 ubClassIndex;
UINT8 ubCursor;
INT8 bSoundType;
UINT8 ubGraphicType;
UINT16 ubGraphicNum;
UINT8 ubWeight; //2 units per kilogram; roughly 1 unit per pound
UINT8 ubPerPocket;
UINT16 usPrice;
UINT8 ubCoolness;
INT8 bReliability;
INT8 bRepairEase;
UINT16 fFlags;
UINT32 uiIndex; // added
INT8 szItemName[80]; //+1 for the null terminator //added
BOOLEAN damageable;
BOOLEAN repairable;
BOOLEAN waterdamages;
BOOLEAN metal;
BOOLEAN sinks;
BOOLEAN showstatus;
BOOLEAN hiddenaddon;
BOOLEAN twohanded;
BOOLEAN notbuyable;
BOOLEAN attachment;
BOOLEAN biggunlist;
BOOLEAN notineditor;
BOOLEAN defaultundroppable;
BOOLEAN unaerodynamic;
BOOLEAN electronic;
BOOLEAN inseparable;
INT8 szLongItemName[80];
INT8 szItemDesc[400];
INT8 szBRName[80];
INT8 szBRDesc[400];
//TODO: quest items, boosters, money
// special item/attachment functions:
BOOLEAN cannon;
BOOLEAN rocketrifle;
BOOLEAN fingerprintid;
BOOLEAN metaldetector;
BOOLEAN gasmask;
BOOLEAN lockbomb;
BOOLEAN flare;
INT16 percentnoisereduction;
BOOLEAN bipod;
INT16 tohitbonus;
INT16 bestlaserrange;
INT16 rangebonus;
INT16 aimbonus;
INT16 minrangeforaimbonus;
INT16 percentapreduction;
INT16 percentstatusdrainreduction;
BOOLEAN grenadelauncher;
BOOLEAN mortar;
BOOLEAN duckbill;
BOOLEAN detonator;
BOOLEAN remotedetonator;
BOOLEAN hidemuzzleflash;
BOOLEAN rocketlauncher;
BOOLEAN singleshotrocketlauncher;
UINT16 discardedlauncheritem;
BOOLEAN brassknuckles;
UINT16 bloodieditem;
BOOLEAN crowbar;
BOOLEAN glgrenade;
BOOLEAN flakjacket;
INT16 hearingrangebonus;
INT16 visionrangebonus;
INT16 nightvisionrangebonus;
INT16 dayvisionrangebonus;
INT16 cavevisionrangebonus;
INT16 brightlightvisionrangebonus;
BOOLEAN leatherjacket;
BOOLEAN batteries;
BOOLEAN needsbatteries;
BOOLEAN xray;
BOOLEAN wirecutters;
BOOLEAN toolkit;
BOOLEAN firstaidkit;
BOOLEAN medicalkit;
BOOLEAN canteen;
BOOLEAN jar;
BOOLEAN canandstring;
BOOLEAN marbles;
BOOLEAN walkman;
BOOLEAN remotetrigger;
BOOLEAN robotremotecontrol;
BOOLEAN camouflagekit;
BOOLEAN locksmithkit;
BOOLEAN mine;
BOOLEAN alcohol;
BOOLEAN hardware;
BOOLEAN medical;
BOOLEAN gascan;
BOOLEAN containsliquid;
BOOLEAN rock;
INT16 damagebonus;
INT16 meleedamagebonus;
INT16 magsizebonus;
INT16 percentautofireapreduction;
INT16 autofirebonus;
INT16 rateoffirebonus;
INT16 burstsizebonus;
INT16 bursttohitbonus;
INT16 percentreadytimeapreduction;
INT16 bulletspeedbonus;
BOOLEAN thermaloptics;
UINT8 percenttunnelvision;
INT16 percentreloadtimeapreduction;
INT16 percentburstfireapreduction;
INT16 camobonus;
UINT16 defaultattachment;
} INVTYPE;
#define FIRST_WEAPON 1
#define FIRST_AMMO 71
#define FIRST_EXPLOSIVE 131
#define FIRST_ARMOUR 161
#define FIRST_MISC 201
#define FIRST_KEY 271
#define NOTHING NONE
typedef enum
{
NONE = 0,
// weapons
GLOCK_17 = FIRST_WEAPON,
GLOCK_18,
BERETTA_92F,
BERETTA_93R,
SW38,
BARRACUDA,
DESERTEAGLE,
M1911,
MP5K,
MAC10, //10
THOMPSON,
COMMANDO,
MP53,
AKSU74,
P90,
TYPE85,
SKS,
DRAGUNOV,
M24,
AUG, //20
G41,
MINI14,
C7,
FAMAS,
AK74,
AKM,
M14,
FNFAL,
G3A3,
G11, //30
M870,
SPAS15,
CAWS,
MINIMI,
RPK74,
HK21E,
COMBAT_KNIFE,
THROWING_KNIFE,
ROCK,
GLAUNCHER, //40
MORTAR,
ROCK2,
CREATURE_YOUNG_MALE_CLAWS,
CREATURE_OLD_MALE_CLAWS,
CREATURE_YOUNG_FEMALE_CLAWS,
CREATURE_OLD_FEMALE_CLAWS,
CREATURE_QUEEN_TENTACLES,
CREATURE_QUEEN_SPIT,
BRASS_KNUCKLES,
UNDER_GLAUNCHER, //50
ROCKET_LAUNCHER,
BLOODCAT_CLAW_ATTACK,
BLOODCAT_BITE,
MACHETE,
ROCKET_RIFLE,
AUTOMAG_III,
CREATURE_INFANT_SPIT,
CREATURE_YOUNG_MALE_SPIT,
CREATURE_OLD_MALE_SPIT,
TANK_CANNON, //60
DART_GUN,
BLOODY_THROWING_KNIFE,
FLAMETHROWER,
CROWBAR,
AUTO_ROCKET_RIFLE, //65
// MADD MARKER
BARRETT, //previously unused
VAL_SILENT, //previously unused
PSG, //previously unused
TAR21, //previously unused
MAX_WEAPONS = ( FIRST_AMMO - 1 ),
CLIP9_15 = FIRST_AMMO,
CLIP9_30,
CLIP9_15_AP,
CLIP9_30_AP,
CLIP9_15_HP,
CLIP9_30_HP,
CLIP38_6,
CLIP38_6_AP,
CLIP38_6_HP,
CLIP45_7,
CLIP45_30,
CLIP45_7_AP,
CLIP45_30_AP,
CLIP45_7_HP,
CLIP45_30_HP,
CLIP357_6,
CLIP357_9,
CLIP357_6_AP,
CLIP357_9_AP,
CLIP357_6_HP,
CLIP357_9_HP,
CLIP545_30_AP,
CLIP545_30_HP,
CLIP556_30_AP,
CLIP556_30_HP,
CLIP762W_10_AP,
CLIP762W_30_AP,
CLIP762W_10_HP,
CLIP762W_30_HP,
CLIP762N_5_AP,
CLIP762N_20_AP,
CLIP762N_5_HP,
CLIP762N_20_HP,
CLIP47_50_SAP,
CLIP57_50_AP,
CLIP57_50_HP,
CLIP12G_7,
CLIP12G_7_BUCKSHOT,
CLIPCAWS_10_SAP,
CLIPCAWS_10_FLECH,
CLIPROCKET_AP,
CLIPROCKET_HE,
CLIPROCKET_HEAT,
CLIPDART_SLEEP,
CLIPFLAME,
// MADD MARKER
CLIP50_11, // unused
CLIP9H_20, // unused
CLIP9_50,
CLIP9_50_AP,
CLIP9_50_HP,
DRUM545_75_AP,
DRUM545_75_HP,
BELT556_200_AP,
BELT556_200_HP,
BELT762N_100_AP,
BELT762N_100_HP,
CLIP57_20_AP,
CLIP57_20_HP,
// unused
// unused
// explosives
STUN_GRENADE = FIRST_EXPLOSIVE,
TEARGAS_GRENADE,
MUSTARD_GRENADE,
MINI_GRENADE,
HAND_GRENADE,
RDX,
TNT,
HMX,
C1,
MORTAR_SHELL,
MINE,
C4,
TRIP_FLARE,
TRIP_KLAXON,
SHAPED_CHARGE,
BREAK_LIGHT,
GL_HE_GRENADE,
GL_TEARGAS_GRENADE,
GL_STUN_GRENADE,
GL_SMOKE_GRENADE,
SMOKE_GRENADE,
TANK_SHELL,
STRUCTURE_IGNITE,
CREATURE_COCKTAIL,
STRUCTURE_EXPLOSION,
GREAT_BIG_EXPLOSION,
BIG_TEAR_GAS,
SMALL_CREATURE_GAS,
LARGE_CREATURE_GAS,
VERY_SMALL_CREATURE_GAS,
// armor
FLAK_JACKET, //= FIRST_ARMOUR, ( We're out of space! )
FLAK_JACKET_18,
FLAK_JACKET_Y,
KEVLAR_VEST,
KEVLAR_VEST_18,
KEVLAR_VEST_Y,
SPECTRA_VEST,
SPECTRA_VEST_18,
SPECTRA_VEST_Y,
KEVLAR_LEGGINGS,
KEVLAR_LEGGINGS_18,
KEVLAR_LEGGINGS_Y,
SPECTRA_LEGGINGS,
SPECTRA_LEGGINGS_18,
SPECTRA_LEGGINGS_Y,
STEEL_HELMET,
KEVLAR_HELMET,
KEVLAR_HELMET_18,
KEVLAR_HELMET_Y,
SPECTRA_HELMET,
SPECTRA_HELMET_18,
SPECTRA_HELMET_Y,
CERAMIC_PLATES,
CREATURE_INFANT_HIDE,
CREATURE_YOUNG_MALE_HIDE,
CREATURE_OLD_MALE_HIDE,
CREATURE_QUEEN_HIDE,
LEATHER_JACKET,
LEATHER_JACKET_W_KEVLAR,
LEATHER_JACKET_W_KEVLAR_18,
LEATHER_JACKET_W_KEVLAR_Y,
CREATURE_YOUNG_FEMALE_HIDE,
CREATURE_OLD_FEMALE_HIDE,
TSHIRT,
TSHIRT_DEIDRANNA,
KEVLAR2_VEST,
KEVLAR2_VEST_18,
KEVLAR2_VEST_Y,
// kits
FIRSTAIDKIT = FIRST_MISC,
MEDICKIT,
TOOLKIT,
LOCKSMITHKIT,
CAMOUFLAGEKIT,
BOOBYTRAPKIT,
// miscellaneous
SILENCER,
SNIPERSCOPE,
BIPOD,
EXTENDEDEAR,
NIGHTGOGGLES,
SUNGOGGLES,
GASMASK,
CANTEEN,
METALDETECTOR,
COMPOUND18,
JAR_QUEEN_CREATURE_BLOOD,
JAR_ELIXIR,
MONEY,
JAR,
JAR_CREATURE_BLOOD,
ADRENALINE_BOOSTER,
DETONATOR,
REMDETONATOR,
VIDEOTAPE,
DEED,
LETTER,
TERRORIST_INFO,
CHALICE,
BLOODCAT_CLAWS,
BLOODCAT_TEETH,
BLOODCAT_PELT,
SWITCH,
// fake items
ACTION_ITEM,
REGEN_BOOSTER,
SYRINGE_3,
SYRINGE_4,
SYRINGE_5,
JAR_HUMAN_BLOOD,
OWNERSHIP,
// additional items
LASERSCOPE,
REMOTEBOMBTRIGGER,
WIRECUTTERS,
DUCKBILL,
ALCOHOL,
UVGOGGLES,
DISCARDED_LAW,
HEAD_1,
HEAD_2,
HEAD_3,
HEAD_4,
HEAD_5,
HEAD_6,
HEAD_7,
WINE,
BEER,
PORNOS,
VIDEO_CAMERA,
ROBOT_REMOTE_CONTROL,
CREATURE_PART_CLAWS,
CREATURE_PART_FLESH,
CREATURE_PART_ORGAN,
REMOTETRIGGER,
GOLDWATCH,
GOLFCLUBS,
WALKMAN,
PORTABLETV,
MONEY_FOR_PLAYERS_ACCOUNT,
CIGARS,
KEY_1 = FIRST_KEY,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_10,
FLASH_SUPPRESSOR,
RPG7,
RPG_HE_ROCKET,
RPG_AP_ROCKET,
RPG_FRAG_ROCKET,
REFLEX_SCOPED,
REFLEX_UNSCOPED,
KEY_18,
KEY_19,
KEY_20,
KEY_21,
KEY_22,
KEY_23,
KEY_24,
KEY_25,
KEY_26,
KEY_27,
KEY_28,
KEY_29,
KEY_30,
KEY_31,
KEY_32, // 302
SILVER_PLATTER,
DUCT_TAPE,
ALUMINUM_ROD,
SPRING,
SPRING_AND_BOLT_UPGRADE,
STEEL_ROD,
QUICK_GLUE,
GUN_BARREL_EXTENDER,
STRING,
TIN_CAN,
STRING_TIED_TO_TIN_CAN,
MARBLES,
LAME_BOY,
COPPER_WIRE,
DISPLAY_UNIT,
FUMBLE_PAK,
XRAY_BULB,
CHEWING_GUM, // 320
FLASH_DEVICE,
BATTERIES,
ELASTIC,
XRAY_DEVICE,
SILVER,
GOLD,
GAS_CAN,
M900, //UNUSED_26,
M950, //UNUSED_27,
M960, //UNUSED_28,
MICRO_UZI, // UNUSED_29,
ENFIELD, // UNUSED_30,
MP5,
MP5SD,
MP5N,
UMP45,
FIVE7,
P7M8,
G36K,
G36C, // 340
MSG90A1,
BENNELLI,
AK103,
UNUSED_42,
UNUSED_43,
UNUSED_44,
UNUSED_45,
UNUSED_46,
UNUSED_47,
UNUSED_48, // 350
MAXITEMS = 5001
} ITEMDEFINE;
#define FIRST_HELMET STEEL_HELMET
#define LAST_HELMET SPECTRA_HELMET_Y
#define FIRST_VEST FLAK_JACKET
#define LAST_VEST KEVLAR2_VEST_Y
#define FIRST_LEGGINGS KEVLAR_LEGGINGS
#define LAST_LEGGINGS SPECTRA_LEGGINGS_Y
#define FIRST_HEAD_ITEM EXTENDEDEAR
#define LAST_HEAD_ITEM SUNGOGGLES
#define MAXATTACHMENTS 30000
extern INVTYPE Item[MAXITEMS];
extern UINT16 Attachment[MAXATTACHMENTS][2];
typedef struct
{
UINT16 usItem;
UINT32 uiItemClass;
INT8 bAttachmentSkillCheck;
INT8 bAttachmentSkillCheckMod;
UINT32 uiIndex;
} AttachmentInfoStruct;
extern AttachmentInfoStruct AttachmentInfo[MAXITEMS+1];
extern UINT16 Launchable[MAXITEMS+1][2];
extern UINT16 CompatibleFaceItems[MAXITEMS+1][2];
extern UINT16 IncompatibleAttachments[MAXATTACHMENTS][2];
typedef enum
{
DESTRUCTION,
COMBINE_POINTS,
TREAT_ARMOUR,
EXPLOSIVE,
EASY_MERGE,
ELECTRONIC_MERGE,
} MergeType;
extern UINT16 Merge[MAXITEMS+1][4];
typedef struct
{
UINT16 usItem;
UINT16 usAttachment[2];
UINT16 usResult;
UINT32 uiIndex;
} ComboMergeInfoStruct;
extern ComboMergeInfoStruct AttachmentComboMerge[MAXITEMS+1];
BOOLEAN EXPLOSIVE_GUN(UINT16 x );
typedef struct IMP_ITEM_CHOICE_TYPE
{
UINT8 ubChoices; // how many valid choices there are in this category
INT16 bItemNo[50]; // room for up to 50 choices in each category
UINT8 ubNumItems; // # of items to select
UINT32 uiIndex;
} IMP_ITEM_CHOICE_TYPE;
enum
{
IMP_DEFAULT = 0,
IMP_RANDOMDEFAULT,
//ATTRIBUTES
IMP_WISDOM,
IMP_DEXTERITY,
IMP_AGILITY,
IMP_STRENGTH,
IMP_HEALTH,
IMP_LEADERSHIP,
IMP_MARKSMANSHIP,
IMP_EXPLOSIVE,
IMP_MECHANICAL,
IMP_MEDICAL,
//SKILLS
IMP_HTH,
IMP_MARTIALARTS,
IMP_NIGHTOPS,
IMP_STEALTHY,
IMP_ROOFTOPS,
IMP_LOCKPICKING,
IMP_ELECTRONICS,
IMP_THROWING,
IMP_KNIFING,
IMP_HEAVYWEAPONS,
IMP_AUTOWEAPONS,
IMP_AMBIDEXTROUS,
IMP_CAMOUFLAGED,
IMP_TEACHING,
IMP_THIEF,
MAX_IMP_ITEM_TYPES
};
extern IMP_ITEM_CHOICE_TYPE gIMPItemChoices[MAX_IMP_ITEM_TYPES];
#endif
+6896
View File
File diff suppressed because it is too large Load Diff
+283
View File
@@ -0,0 +1,283 @@
#ifndef ITEMS_H
#define ITEMS_H
#include "Item Types.h"
#include "Soldier Control.h"
#include "Overhead Types.h"
// Snap: Moved here from opplist.cpp
// These defined are no longer used to calculate item bonuses,
// but for lack of anything better, they are still used in other places
#define NIGHTSIGHTGOGGLES_BONUS 2 * STRAIGHT_RATIO
#define UVGOGGLES_BONUS 4 * STRAIGHT_RATIO
extern UINT8 SlotToPocket[7];
extern BOOLEAN WeaponInHand( SOLDIERTYPE * pSoldier );
extern INT8 FindObj( SOLDIERTYPE * pSoldier, UINT16 usItem );
INT8 FindAmmo( SOLDIERTYPE * pSoldier, UINT8 ubCalibre, UINT8 ubMagSize, INT8 bExcludeSlot );
extern INT8 FindAttachment( OBJECTTYPE * pObj, UINT16 usItem );
extern INT8 FindObjClass( SOLDIERTYPE * pSoldier, UINT32 usItemClass );
extern INT8 FindObjClassAfterSlot( SOLDIERTYPE * pSoldier, INT8 bStart, UINT32 usItemClass );
extern INT8 FindAIUsableObjClass( SOLDIERTYPE * pSoldier, UINT32 usItemClass );
extern INT8 FindAIUsableObjClassWithin( SOLDIERTYPE * pSoldier, UINT32 usItemClass, INT8 bLower, INT8 bUpper );
extern INT8 FindEmptySlotWithin( SOLDIERTYPE * pSoldier, INT8 bLower, INT8 bUpper );
extern INT8 FindExactObj( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj );
extern INT8 FindObjInObjRange( SOLDIERTYPE * pSoldier, UINT16 usItem1, UINT16 usItem2 );
extern INT8 FindLaunchable( SOLDIERTYPE * pSoldier, UINT16 usWeapon );
extern INT8 FindGLGrenade( SOLDIERTYPE * pSoldier );
extern INT8 FindThrowableGrenade( SOLDIERTYPE * pSoldier );
extern INT8 FindUsableObj( SOLDIERTYPE * pSoldier, UINT16 usItem );
extern void DeleteObj(OBJECTTYPE * pObj );
extern void CopyObj( OBJECTTYPE * pSourceObj, OBJECTTYPE * pTargetObj );
extern void SwapObjs( OBJECTTYPE * pObj1, OBJECTTYPE * pObj2 );
extern void SwapWithinObj( OBJECTTYPE * pObj, UINT8 ubIndex1, UINT8 ubIndex2 );
extern void RemoveObjFrom( OBJECTTYPE * pObj, UINT8 ubRemoveIndex );
//Returns true if swapped, false if added to end of stack
extern BOOLEAN PlaceObjectAtObjectIndex( OBJECTTYPE * pSourceObj, OBJECTTYPE * pTargetObj, UINT8 ubIndex );
extern void GetObjFrom( OBJECTTYPE * pObj, UINT8 ubGetIndex, OBJECTTYPE * pDest );
extern BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYPE * pAttachment, BOOLEAN playSound );
extern BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYPE * pAttachment );
extern BOOLEAN RemoveAttachment( OBJECTTYPE * pObj, INT8 bAttachPos, OBJECTTYPE * pNewObj );
extern UINT8 CalculateObjectWeight( OBJECTTYPE *pObject );
extern UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier );
extern UINT16 TotalPoints( OBJECTTYPE * pObj );
extern UINT16 UseKitPoints( OBJECTTYPE * pObj, UINT16 usPoints, SOLDIERTYPE *pSoldier );
extern BOOLEAN EmptyWeaponMagazine( OBJECTTYPE * pWeapon, OBJECTTYPE *pAmmo );
extern BOOLEAN CreateItem( UINT16 usItem, INT8 bStatus, OBJECTTYPE * pObj );
extern BOOLEAN CreateItems( UINT16 usItem, INT8 bStatus, UINT8 ubNumber, OBJECTTYPE * pObj );
extern BOOLEAN CreateMoney( UINT32 uiMoney, OBJECTTYPE * pObj );
extern UINT16 DefaultMagazine( UINT16 usItem );
UINT16 RandomMagazine( UINT16 usItem, UINT8 ubPercentStandard );
UINT16 RandomMagazine( OBJECTTYPE * pGun, UINT8 ubPercentStandard );
extern BOOLEAN ReloadGun( SOLDIERTYPE * pSoldier, OBJECTTYPE * pGun, OBJECTTYPE * pAmmo );
UINT8 ItemSlotLimit( UINT16 usItem, INT8 bSlot );
// Function to put an item in a soldier profile
// It's very primitive, just finds an empty place!
BOOLEAN PlaceObjectInSoldierProfile( UINT8 ubProfile, OBJECTTYPE *pObject );
BOOLEAN RemoveObjectFromSoldierProfile( UINT8 ubProfile, UINT16 usItem );
INT8 FindObjectInSoldierProfile( UINT8 ubProfile, UINT16 usItem );
BOOLEAN ObjectExistsInSoldierProfile( UINT8 ubProfile, UINT16 usItem );
void SetMoneyInSoldierProfile( UINT8 ubProfile, UINT32 uiMoney );
void CheckEquipmentForDamage( SOLDIERTYPE *pSoldier, INT32 iDamage );
BOOLEAN ArmBomb( OBJECTTYPE * pObj, INT8 bSetting );
// NOTE TO ANDREW:
//
// The following functions expect that pObj points to the object
// "in the cursor", which should have memory allocated for it already
BOOLEAN PlaceObject( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj );
// Send fNewItem to true to set off new item glow in inv panel
BOOLEAN AutoPlaceObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN fNewItem );
BOOLEAN RemoveObjectFromSlot( SOLDIERTYPE * pSoldier, INT8 bPos, OBJECTTYPE * pObj );
void RemoveInvObject( SOLDIERTYPE *pSoldier, UINT16 usItem );
UINT8 SwapKeysToSlot( SOLDIERTYPE * pSoldier, INT8 bKeyRingPosition, OBJECTTYPE * pObj );
// create a keyobject
BOOLEAN CreateKeyObject( OBJECTTYPE * pObj , UINT8 ubNumberOfKeys, UINT8 ubKeyIdValue );
BOOLEAN DeleteKeyObject( OBJECTTYPE * pObj );
BOOLEAN AllocateObject( OBJECTTYPE **pObj );
// removes a key from a *KEYRING* slot
BOOLEAN RemoveKeyFromSlot( SOLDIERTYPE * pSoldier, INT8 bKeyRingPosition, OBJECTTYPE * pObj );
// take several
BOOLEAN RemoveKeysFromSlot( SOLDIERTYPE * pSoldier, INT8 bKeyRingPosition, UINT8 ubNumberOfKeys ,OBJECTTYPE * pObj );
// add the keys to an inventory slot
UINT8 AddKeysToSlot( SOLDIERTYPE * pSoldier, INT8 bKeyRingPosition, OBJECTTYPE * pObj );
//Kris: December 9, 1997
//I need a bunch of validation functions for ammo, attachments, etc., so I'll be adding them here.
//Chris, maybe you might find these useful, or add your own. I don't really know what I'm doing yet,
//so feel free to correct me...
//Simple check to see if the item has any attachments
BOOLEAN ItemHasAttachments( OBJECTTYPE *pItem );
//Determine if this item can receive this attachment. This is different, in that it may
//be possible to have this attachment on this item, but may already have an attachment on
//it which doesn't work simultaneously with the new attachment (like a silencer and duckbill).
BOOLEAN ValidItemAttachment( OBJECTTYPE * pObj, UINT16 usAttachment, BOOLEAN fAttemptingAttachment );
// Determines if it is possible to merge an item with any item whose class
// is the same as the indicated item
BOOLEAN ValidAttachmentClass( UINT16 usAttachment, UINT16 usItem );
//Determines if it is possible to equip this weapon with this ammo.
BOOLEAN ValidAmmoType( UINT16 usItem, UINT16 usAmmoType );
//Determines if this item is a two handed item.
BOOLEAN TwoHandedItem( UINT16 usItem );
//Existing functions without header def's, added them here, just incase I'll need to call
//them from the editor.
BOOLEAN ValidAttachment( UINT16 usAttachment, UINT16 usItem );
BOOLEAN ValidLaunchable( UINT16 usLaunchable, UINT16 usItem );
UINT16 GetLauncherFromLaunchable( UINT16 usLaunchable );
BOOLEAN ValidMerge( UINT16 usMerge, UINT16 usItem );
BOOLEAN EvaluateValidMerge( UINT16 usMerge, UINT16 usItem, UINT16 * pusResult, UINT8 * pubType );
// is the item passed a medical/ first aid kit? and what type?
INT8 IsMedicalKitItem( OBJECTTYPE *pObject );
BOOLEAN AutoReload( SOLDIERTYPE * pSoldier );
INT8 FindAmmoToReload( SOLDIERTYPE * pSoldier, INT8 bWeaponIn, INT8 bExcludeSlot );
void SwapOutHandItem( SOLDIERTYPE * pSoldier );
void SwapHandItems( SOLDIERTYPE * pSoldier );
INT8 FindAttachmentByClass( OBJECTTYPE * pObj, UINT32 uiItemClass );
void RemoveObjs( OBJECTTYPE * pObj, UINT8 ubNumberToRemove );
void WaterDamage( SOLDIERTYPE *pSoldier );
INT8 FindObjWithin( SOLDIERTYPE * pSoldier, UINT16 usItem, INT8 bLower, INT8 bUpper );
BOOLEAN ApplyCammo( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs );
UINT32 ConvertProfileMoneyValueToObjectTypeMoneyValue( UINT8 ubStatus );
UINT8 ConvertObjectTypeMoneyValueToProfileMoneyValue( UINT32 uiMoneyAmount );
BOOLEAN CheckForChainReaction( UINT16 usItem, INT8 bStatus, INT8 bDamage, BOOLEAN fOnGround );
BOOLEAN ItemIsLegal( UINT16 usItemIndex );
BOOLEAN ExtendedGunListGun( UINT16 usGun );
UINT16 StandardGunListReplacement( UINT16 usGun );
UINT16 FindReplacementMagazine( UINT8 ubCalibre, UINT8 ubMagSize, UINT8 ubAmmoType);
UINT16 FindReplacementMagazineIfNecessary( UINT16 usOldGun, UINT16 usOldAmmo, UINT16 usNewGun );
BOOLEAN DamageItemOnGround( OBJECTTYPE * pObject, INT16 sGridNo, INT8 bLevel, INT32 iDamage, UINT8 ubOwner );
BOOLEAN ApplyCanteen( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs );
BOOLEAN ApplyElixir( SOLDIERTYPE * pSoldier, OBJECTTYPE * pObj, BOOLEAN *pfGoodAPs );
BOOLEAN CompatibleFaceItem( UINT16 usItem1, UINT16 usItem2 );
UINT32 MoneySlotLimit( INT8 bSlot );
void CheckEquipmentForFragileItemDamage( SOLDIERTYPE *pSoldier, INT32 iDamage );
// Range of Xray device
#define XRAY_RANGE 40
// Seconds that Xray lasts
#define XRAY_TIME 5
extern void ActivateXRayDevice( SOLDIERTYPE * pSoldier );
extern void TurnOffXRayEffects( SOLDIERTYPE * pSoldier );
extern INT8 FindLaunchableAttachment( OBJECTTYPE * pObj, UINT16 usWeapon );
void DamageObj( OBJECTTYPE * pObj, INT8 bAmount );
UINT16 MagazineClassIndexToItemType(UINT16 usMagIndex);
// Item property-related stuff added by Madd Mugsy
BOOLEAN IsScoped( const OBJECTTYPE * pObj );
INT16 GetAimBonus( OBJECTTYPE * pObj, INT32 iRange, UINT8 ubAimTime );
INT16 GetMinAimBonusRange( OBJECTTYPE * pObj );
INT16 GetToHitBonus( OBJECTTYPE * pObj, INT32 iRange, UINT8 bLightLevel, BOOLEAN fProneStance = FALSE );
UINT32 FindRangeBonusAttachment( OBJECTTYPE * pObj );
INT16 GetRangeBonus( OBJECTTYPE * pObj );
INT16 GetBurstToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE );
INT16 GetDamageBonus( OBJECTTYPE * pObj );
INT16 GetMeleeDamageBonus( OBJECTTYPE * pObj );
INT16 GetPercentAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentAutofireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentBurstFireAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentReadyTimeAPReduction( OBJECTTYPE * pObj );
INT16 GetPercentReloadTimeAPReduction( OBJECTTYPE * pObj );
INT16 GetAutofireBonus( OBJECTTYPE * pObj );
INT16 GetRateOfFireBonus( OBJECTTYPE * pObj );
INT16 GetBurstSizeBonus( OBJECTTYPE * pObj );
BOOLEAN HasFastBurst( OBJECTTYPE * pObj );
INT16 GetMagSizeBonus( OBJECTTYPE * pObj );
// Snap: GetTotalVisionRangeBonus checks for light levels
// and returns cumulative bonus from the following functions:
//
// GetVisionRangeBonus applies to all light levels
// GetNightVisionRangeBonus: bLightLevel > NORMAL_LIGHTLEVEL_DAY, above ground only
// GetCaveVisionRangeBonus: bLightLevel > NORMAL_LIGHTLEVEL_DAY, underground only
// GetDayVisionRangeBonus: NORMAL_LIGHTLEVEL_DAY <= bLightLevel < NORMAL_LIGHTLEVEL_NIGHT
// GetBrightLightVisionRangeBonus: bLightLevel < NORMAL_LIGHTLEVEL_DAY
// (remember: darker is higher!)
INT16 GetTotalVisionRangeBonus( SOLDIERTYPE * pSoldier, UINT8 bLightLevel );
// Snap: Scale night vision bonus with light level
INT16 NightBonusScale( INT16 bonus, UINT8 bLightLevel );
UINT8 GetPercentTunnelVision( SOLDIERTYPE * pSoldier );
BOOLEAN HasThermalOptics( SOLDIERTYPE * pSoldier );
INT8 FindHearingAid( SOLDIERTYPE * pSoldier );
INT16 GetHearingRangeBonus( SOLDIERTYPE * pSoldier );
INT8 IsGrenadeLauncher( OBJECTTYPE * pObj );
INT8 GetGrenadeLauncherStatus( OBJECTTYPE * pObj );
BOOLEAN IsGrenadeLauncherAttached( OBJECTTYPE * pObj );
INT8 FindAttachment_GrenadeLauncher( OBJECTTYPE * pObj );
UINT16 GetAttachedGrenadeLauncher( OBJECTTYPE * pObj );
INT8 FindRocketLauncher( SOLDIERTYPE * pSoldier );
INT8 FindRocketLauncherOrCannon( SOLDIERTYPE * pSoldier );
INT8 FindNonSmokeLaunchable( SOLDIERTYPE * pSoldier, UINT16 usWeapon );
INT8 FindNonSmokeLaunchableAttachment( OBJECTTYPE * pObj, UINT16 usWeapon );
UINT16 PickARandomLaunchable(UINT16 itemIndex);
BOOLEAN IsFlashSuppressor( OBJECTTYPE * pObj );
INT16 GetFlashSuppressorStatus( OBJECTTYPE * pObj );
BOOLEAN IsRemoteDetonator( OBJECTTYPE * pObj );
BOOLEAN IsDetonator( OBJECTTYPE * pObj );
BOOLEAN IsDuckbill( OBJECTTYPE * pObj );
// Snap: Returns CUMULATIVE noise volume modifier, with component status factored in.
// Noise volume is then calculated as volume * GetPercentNoiseVolume / 100
UINT16 GetPercentNoiseVolume( OBJECTTYPE * pObj );
INT8 FindFirstArmourAttachment( OBJECTTYPE * pObj );
INT16 GetAttachedArmourBonus( OBJECTTYPE * pObj );
INT16 GetBulletSpeedBonus( OBJECTTYPE * pObj );
INT8 FindGasMask( SOLDIERTYPE * pSoldier );
INT8 FindLockBomb( SOLDIERTYPE * pSoldier );
INT8 FindMetalDetector( SOLDIERTYPE * pSoldier );
INT8 FindCannon( SOLDIERTYPE * pSoldier );
INT8 FindUsableCrowbar( SOLDIERTYPE * pSoldier );
INT8 FindToolkit( SOLDIERTYPE * pSoldier );
BOOLEAN IsDetonatorAttached( OBJECTTYPE * pObj );
BOOLEAN IsRemoteDetonatorAttached( OBJECTTYPE * pObj );
INT8 FindAttachedBatteries( OBJECTTYPE * pObj );
INT8 FindMedKit( SOLDIERTYPE * pSoldier );
INT8 FindFirstAidKit( SOLDIERTYPE * pSoldier );
INT8 FindLocksmithKit( SOLDIERTYPE * pSoldier );
INT8 FindCamoKit( SOLDIERTYPE * pSoldier );
INT8 FindWalkman( SOLDIERTYPE * pSoldier );
INT8 FindTrigger( SOLDIERTYPE * pSoldier );
INT8 FindRemoteControl( SOLDIERTYPE * pSoldier );
INT16 GetWornCamo( SOLDIERTYPE * pSoldier );
INT16 GetCamoBonus( OBJECTTYPE * pObj );
void ApplyEquipmentBonuses(SOLDIERTYPE * pSoldier);
#endif
+2163
View File
File diff suppressed because it is too large Load Diff
+255
View File
@@ -0,0 +1,255 @@
#ifndef _KEYS_H_
#define _KEYS_H_
#include "types.h"
#include "FileMan.h"
typedef struct
{
UINT16 usItem; // index in item table for key
UINT8 fFlags; // flags...
UINT16 usSectorFound; // where and
UINT16 usDateFound; // when the key was found
} KEY;
#define KEY_USED 0x01
#define LOCK_UNOPENABLE 255
#define NO_KEY 255
#define MAX_KEYS_PER_LOCK 4
#define LOCK_REGULAR 1
#define LOCK_PADLOCK 2
#define LOCK_CARD 3
#define LOCK_ELECTRONIC 4
#define LOCK_SPECIAL 5
/*
typedef struct
{
UINT8 ubKeyID[MAX_KEYS_PER_LOCK];
UINT8 ubLockType; // numeric lock type value... easier to use than flags!
INT8 bPickSkillAdjustment; // difficulty to pick a lock which takes this key
INT8 bSmashSkillAdjustment; // the strength of the lock (resistance to smashing)
} LOCK;
*/
#define MAXLOCKDESCLENGTH 40
typedef struct
{
UINT8 ubEditorName[ MAXLOCKDESCLENGTH ]; // name to display in editor
UINT16 usKeyItem; // key for this door uses which graphic (item #)?
UINT8 ubLockType; // regular, padlock, electronic, etc
UINT8 ubPickDifficulty; // difficulty to pick such a lock
UINT8 ubSmashDifficulty; // difficulty to smash such a lock
UINT8 ubFiller;
} LOCK;
// Defines below for the perceived value of the door
#define DOOR_PERCEIVED_UNKNOWN 0
#define DOOR_PERCEIVED_LOCKED 1
#define DOOR_PERCEIVED_UNLOCKED 2
#define DOOR_PERCEIVED_BROKEN 3
#define DOOR_PERCEIVED_TRAPPED 1
#define DOOR_PERCEIVED_UNTRAPPED 2
typedef struct
{
INT16 sGridNo;
BOOLEAN fLocked; // is the door locked
UINT8 ubTrapLevel; // difficulty of finding the trap, 0-10
UINT8 ubTrapID; // the trap type (0 is no trap)
UINT8 ubLockID; // the lock (0 is no lock)
INT8 bPerceivedLocked; // The perceived lock value can be different than the fLocked.
// Values for this include the fact that we don't know the status of
// the door, etc
INT8 bPerceivedTrapped; // See above, but with respect to traps rather than locked status
INT8 bLockDamage; // Damage to the lock
INT8 bPadding[4]; // extra bytes
} DOOR;
typedef enum
{
NO_TRAP = 0,
EXPLOSION,
ELECTRIC,
SIREN,
SILENT_ALARM,
BROTHEL_SIREN,
SUPER_ELECTRIC,
NUM_DOOR_TRAPS
} DoorTrapTypes;
#define DOOR_TRAP_STOPS_ACTION 0x01
#define DOOR_TRAP_RECURRING 0x02
#define DOOR_TRAP_SILENT 0x04
typedef struct
{
UINT8 fFlags; // stops action? recurring trap?
} DOORTRAP;
//The status of the door, either open or closed
#define DOOR_OPEN 0x01
#define DOOR_PERCEIVED_OPEN 0x02
#define DOOR_PERCEIVED_NOTSET 0x04
#define DOOR_BUSY 0x08
#define DOOR_HAS_TIN_CAN 0x10
#define DONTSETDOORSTATUS 2
typedef struct
{
INT16 sGridNo;
UINT8 ubFlags;
} DOOR_STATUS;
// This is the number of different types of doors we can have
// in one map at a time...
#define NUM_KEYS 64
#define NUM_LOCKS 64
#define INVALID_KEY_NUMBER 255
#define ANYKEY 252
#define AUTOUNLOCK 253
#define OPENING_NOT_POSSIBLE 254
extern KEY KeyTable[NUM_KEYS];
extern LOCK LockTable[NUM_LOCKS];
extern DOORTRAP DoorTrapTable[NUM_DOOR_TRAPS];
extern BOOLEAN AddKeysToKeyRing( SOLDIERTYPE *pSoldier, UINT8 ubKeyID, UINT8 ubNumber );
extern BOOLEAN RemoveKeyFromKeyRing( SOLDIERTYPE *pSoldier, UINT8 ubPos, OBJECTTYPE * pObj );
extern BOOLEAN RemoveAllOfKeyFromKeyRing( SOLDIERTYPE *pSoldier, UINT8 ubPos, OBJECTTYPE * pObj );
extern BOOLEAN KeyExistsInInventory( SOLDIERTYPE *pSoldier, UINT8 ubKeyID );
extern BOOLEAN KeyExistsInKeyRing( SOLDIERTYPE *pSoldier, UINT8 ubKeyID, UINT8 * pubPos );
extern BOOLEAN SoldierHasKey( SOLDIERTYPE *pSoldier, UINT8 ubKeyID );
extern STR16 sKeyDescriptionStrings[];
/**********************************
* Door utils add by Kris Morness *
**********************************/
//Dynamic array of Doors. For general game purposes, the doors that are locked and/or trapped
//are permanently saved within the map, and are loaded and allocated when the map is loaded. Because
//the editor allows more doors to be added, or removed, the actual size of the DoorTable may change.
extern DOOR *DoorTable;
//Current number of doors in world.
extern UINT8 gubNumDoors;
//Current max number of doors. This is only used by the editor. When adding doors to the
//world, we may run out of space in the DoorTable, so we will allocate a new array with extra slots,
//then copy everything over again. gubMaxDoors holds the arrays actual number of slots, even though
//the current number (gubNumDoors) will be <= to it.
extern UINT8 gubMaxDoors;
//File I/O for loading the door information from the map. This automatically allocates
//the exact number of slots when loading.
extern void LoadDoorTableFromMap( INT8 **hBuffer );
//Saves the existing door information to the map. Before it actually saves, it'll verify that the
//door still exists. Otherwise, it'll ignore it. It is possible in the editor to delete doors in
//many different ways, so I opted to put it in the saving routine.
extern void SaveDoorTableToMap( HWFILE fp );
//The editor adds locks to the world. If the gridno already exists, then the currently existing door
//information is overwritten.
extern void AddDoorInfoToTable( DOOR *pDoor );
//When the editor removes a door from the world, this function looks for and removes accompanying door
//information. If the entry is not the last entry, the last entry is move to it's current slot, to keep
//everything contiguous.
extern void RemoveDoorInfoFromTable( INT32 iMapIndex );
//This is the link to see if a door exists at a gridno.
DOOR * FindDoorInfoAtGridNo( INT32 iMapIndex );
//Upon world deallocation, the door table needs to be deallocated.
extern void TrashDoorTable();
BOOLEAN AttemptToUnlockDoor( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN AttemptToLockDoor( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN AttemptToSmashDoor( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN AttemptToPickLock( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN AttemptToBlowUpLock( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN AttemptToUntrapDoor( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN ExamineDoorForTraps( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN HasDoorTrapGoneOff( SOLDIERTYPE * pSoldier, DOOR * pDoor );
void HandleDoorTrap( SOLDIERTYPE * pSoldier, DOOR * pDoor );
// Updates the perceived value to the user of the state of the door
void UpdateDoorPerceivedValue( DOOR *pDoor );
//Saves the Door Table array to the temp file
BOOLEAN SaveDoorTableToDoorTableTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ );
//Load the door table from the temp file
BOOLEAN LoadDoorTableFromDoorTableTempFile( );
// Adds a door to the Door status array. As the user comes across the door, they are added.
// if the door already exists, nothing happens
// fOpen is True if the door is to be initially open, false if it is closed
// fInitiallyPercieveOpen is true if the door is to be initially open, else false
BOOLEAN ModifyDoorStatus( INT16 sGridNo, BOOLEAN fOpen, BOOLEAN fInitiallyPercieveOpen );
//Deletes the door status array
void TrashDoorStatusArray( );
// Returns true if the door is open, otherwise false
BOOLEAN IsDoorOpen( INT16 sGridNo );
//Returns true if the door is perceioved as open
BOOLEAN IsDoorPerceivedOpen( INT16 sGridNo );
// Saves the Door Status array to the MapTempfile
BOOLEAN SaveDoorStatusArrayToDoorStatusTempFile( INT16 sSectorX, INT16 sSectorY, INT8 bSectorZ );
//Load the door status from the door status temp file
BOOLEAN LoadDoorStatusArrayFromDoorStatusTempFile();
//Modify the Doors open status
BOOLEAN SetDoorOpenStatus( INT16 sGridNo, BOOLEAN fOpen );
//Modify the doors perceived open status
BOOLEAN SetDoorPerceivedOpenStatus( INT16 sGridNo, BOOLEAN fPerceivedOpen );
//Save the key table to the saved game file
BOOLEAN SaveKeyTableToSaveGameFile( HWFILE hFile );
//Load the key table from the saved game file
BOOLEAN LoadKeyTableFromSaveedGameFile( HWFILE hFile );
// Returns a doors status value, NULL if not found
DOOR_STATUS *GetDoorStatus( INT16 sGridNo );
BOOLEAN UpdateDoorStatusPerceivedValue( INT16 sGridNo );
BOOLEAN AllMercsLookForDoor( INT16 sGridNo, BOOLEAN fUpdateValue );
BOOLEAN MercLooksForDoors( SOLDIERTYPE *pSoldier, BOOLEAN fUpdateValue );
void UpdateDoorGraphicsFromStatus( BOOLEAN fUsePerceivedStatus, BOOLEAN fDirty );
BOOLEAN AttemptToCrowbarLock( SOLDIERTYPE * pSoldier, DOOR * pDoor );
BOOLEAN LoadLockTable( void );
void ExamineDoorsOnEnteringSector( );
void HandleDoorsChangeWhenEnteringSectorCurrentlyLoaded( );
void AttachStringToDoor( INT16 sGridNo );
void DropKeysInKeyRing( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, INT8 bVisible, BOOLEAN fAddToDropList, INT32 iDropListSlot, BOOLEAN fUseUnLoaded );
#endif
+5388
View File
File diff suppressed because it is too large Load Diff
+172
View File
@@ -0,0 +1,172 @@
#ifndef LOS_H
#define LOS_H
//#define LOS_DEBUG
// fixed-point arithmetic definitions start here
typedef INT32 FIXEDPT;
// rem 1 signed bit at the top
#define FIXEDPT_WHOLE_BITS 11
#define FIXEDPT_FRACTIONAL_BITS 20
#define FIXEDPT_FRACTIONAL_RESOLUTION 1048576
#define INT32_TO_FIXEDPT( n ) ( (n) << FIXEDPT_FRACTIONAL_BITS )
#define FIXEDPT_TO_INT32( n ) ( (n) / FIXEDPT_FRACTIONAL_RESOLUTION )
#define FIXEDPT_TO_TILE_NUM( n ) (FIXEDPT_TO_INT32( (n) ) / CELL_X_SIZE)
#define FIXEDPT_TO_LOS_INDEX( n ) (CONVERT_WITHINTILE_TO_INDEX( FIXEDPT_TO_INT32( (n) ) % CELL_X_SIZE))
// fixed-point arithmetic definitions end here
#define OK_CHANCE_TO_GET_THROUGH 10
enum CollisionEnums
{
COLLISION_NONE,
COLLISION_GROUND,
COLLISION_MERC,
COLLISION_WINDOW_SOUTHEAST,
COLLISION_WINDOW_SOUTHWEST,
COLLISION_WINDOW_NORTHEAST,
COLLISION_WINDOW_NORTHWEST,
COLLISION_WINDOW_NORTH,
COLLISION_WALL_SOUTHEAST,
COLLISION_WALL_SOUTHWEST,
COLLISION_WALL_NORTHEAST,
COLLISION_WALL_NORTHWEST,
COLLISION_STRUCTURE,
COLLISION_ROOF,
COLLISION_INTERIOR_ROOF,
COLLISION_STRUCTURE_Z,
COLLISION_WATER,
} ;
INT32 CheckForCollision( FLOAT dX, FLOAT dY, FLOAT dZ, FLOAT dDeltaX, FLOAT dDeltaY, FLOAT dDeltaZ, INT16 *pusStructureID, FLOAT *pdNormalX, FLOAT *pdNormalY, FLOAT *pdNormalZ );
INT8 ChanceToGetThrough( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ );
INT8 FireBulletGivenTarget( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, UINT16 usHandItem, INT16 sHitBy, BOOLEAN fBuckshot, BOOLEAN fFake );
INT32 SoldierToSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, UINT8 ubSightLimit, INT8 bAware );
INT32 SoldierToLocationLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, UINT8 ubSightLimit, INT8 bAware );
INT32 SoldierTo3DLocationLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bCubeLevel, UINT8 ubSightLimit, INT8 bAware );
INT32 SoldierToBodyPartLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, UINT8 ubAimLocation, UINT8 ubTileSightLimit, INT8 bAware );
INT32 SoldierToVirtualSoldierLineOfSightTest( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bStance, UINT8 ubTileSightLimit, INT8 bAware );
UINT8 SoldierToSoldierChanceToGetThrough( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier );
UINT8 SoldierToSoldierBodyPartChanceToGetThrough( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, UINT8 ubAimLocation );
UINT8 AISoldierToSoldierChanceToGetThrough( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier );
UINT8 AISoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bCubeLevel );
UINT8 SoldierToLocationChanceToGetThrough( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, INT8 bLevel, INT8 bCubeLevel, UINT8 ubTargetID );
INT32 SoldierToLocationVisibleDistance( SOLDIERTYPE * pStartSoldier, INT16 sGridNo, UINT8 ubTileSightLimit, INT8 bAware );
INT16 SoldierToLocationWindowTest( SOLDIERTYPE * pStartSoldier, INT16 sEndGridNo );
INT32 LocationToLocationLineOfSightTest( INT16 sStartGridNo, INT8 bStartLevel, INT16 sEndGridNo, INT8 bEndLevel, UINT8 ubTileSightLimit, INT8 bAware );
BOOLEAN CalculateSoldierZPos( SOLDIERTYPE * pSoldier, UINT8 ubPosType, FLOAT * pdZPos );
BOOLEAN SoldierToSoldierLineOfSightTimingTest( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier, UINT8 ubSightLimit, INT8 bAware );
BOOLEAN TestFireBullet( SOLDIERTYPE * pStartSoldier, SOLDIERTYPE * pEndSoldier );
void DoChrisTest( SOLDIERTYPE * pSoldier );
#define HEIGHT_UNITS 256
#define HEIGHT_UNITS_PER_INDEX (HEIGHT_UNITS / PROFILE_Z_SIZE)
#define MAX_STRUCTURE_HEIGHT 50
// 5.12 == HEIGHT_UNITS / MAX_STRUCTURE_HEIGHT
#define CONVERT_PIXELS_TO_HEIGHTUNITS( n ) ((n) * HEIGHT_UNITS / MAX_STRUCTURE_HEIGHT)
#define CONVERT_PIXELS_TO_INDEX( n ) ((n) * HEIGHT_UNITS / MAX_STRUCTURE_HEIGHT / HEIGHT_UNITS_PER_INDEX)
#define CONVERT_HEIGHTUNITS_TO_INDEX( n ) ((n) / HEIGHT_UNITS_PER_INDEX)
#define CONVERT_HEIGHTUNITS_TO_DISTANCE( n ) ((n) / (HEIGHT_UNITS / CELL_X_SIZE) )
#define CONVERT_HEIGHTUNITS_TO_PIXELS( n ) ((n) * MAX_STRUCTURE_HEIGHT / HEIGHT_UNITS )
#define CONVERT_WITHINTILE_TO_INDEX( n ) ((n) >> 1)
#define CONVERT_INDEX_TO_WITHINTILE( n ) ((n) << 1)
#define CONVERT_INDEX_TO_PIXELS( n ) ((n) * MAX_STRUCTURE_HEIGHT * HEIGHT_UNITS_PER_INDEX / HEIGHT_UNITS)
#define TREE_SIGHT_REDUCTION 6
#define NORMAL_TREES 10
enum {
LOS_POS,
FIRING_POS,
TARGET_POS,
HEAD_TARGET_POS,
TORSO_TARGET_POS,
LEGS_TARGET_POS,
HEIGHT
};
// 191 is 6' (structures of height 3)
// 127 is 4' (structures of height 2)
// 63 is 2' (structures of height 1)
#define STANDING_HEIGHT 191.0f
#define STANDING_LOS_POS 175.0f
#define STANDING_FIRING_POS 175.0f
#define STANDING_HEAD_TARGET_POS 175.0f
#define STANDING_HEAD_BOTTOM_POS 159.0f
#define STANDING_TORSO_TARGET_POS 127.0f
#define STANDING_TORSO_BOTTOM_POS 95.0f
#define STANDING_LEGS_TARGET_POS 47.0f
#define STANDING_TARGET_POS STANDING_HEAD_TARGET_POS
#define CROUCHED_HEIGHT 130.0f
#define CROUCHED_LOS_POS 111.0f
#define CROUCHED_FIRING_POS 111.0f
#define CROUCHED_HEAD_TARGET_POS 111.0f
#define CROUCHED_HEAD_BOTTOM_POS 95.0f
#define CROUCHED_TORSO_TARGET_POS 71.0f
#define CROUCHED_TORSO_BOTTOM_POS 47.0f
#define CROUCHED_LEGS_TARGET_POS 31.0f
#define CROUCHED_TARGET_POS CROUCHED_HEAD_TARGET_POS
#define PRONE_HEIGHT 63.0f
#define PRONE_LOS_POS 31.0f
#define PRONE_FIRING_POS 31.0f
#define PRONE_TORSO_TARGET_POS 31.0f
#define PRONE_HEAD_TARGET_POS 31.0f
#define PRONE_LEGS_TARGET_POS 31.0f
#define PRONE_TARGET_POS PRONE_HEAD_TARGET_POS
#define WALL_HEIGHT_UNITS HEIGHT_UNITS
#define WINDOW_BOTTOM_HEIGHT_UNITS 87
#define WINDOW_TOP_HEIGHT_UNITS 220
#define CLOSE_TO_FIRER 25
#define VERY_CLOSE_TO_FIRER 21
#ifdef LOS_DEBUG
typedef struct LOSResults
{
BOOLEAN fLOSTestPerformed;
BOOLEAN fLOSClear;
BOOLEAN fOutOfRange;
INT32 iDistance;
INT32 iMaxDistance;
UINT8 ubTreeSpotsHit;
INT32 iStartX;
INT32 iStartY;
INT32 iStartZ;
INT32 iEndX;
INT32 iEndY;
INT32 iEndZ;
INT32 iStoppedX;
INT32 iStoppedY;
INT32 iStoppedZ;
INT32 iCurrCubesZ;
UINT8 ubChanceToGetThrough;
} LOSResults;
extern LOSResults gLOSTestResults;
#endif
void MoveBullet( INT32 iBullet );
//BOOLEAN FireBullet2( SOLDIERTYPE * pFirer, FLOAT dEndX, FLOAT dEndY, FLOAT dEndZ, INT16 sHitBy );
#endif
+635
View File
@@ -0,0 +1,635 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "edit_sys.h"
#else
#include <stdio.h>
#include "fileMan.h"
#include "types.h"
#include "Map Information.h"
#include "Soldier Init List.h"
#include "Random.h"
#include "worlddef.h"
#include "worldman.h"
#include "renderworld.h"
#include "EditorMercs.h"
#include "Exit Grids.h"
#include "Isometric Utils.h"
#include "ja2.h"
#include "Animation Data.h"
#include "Road Smoothing.h"
#include "sys globals.h"
#include "message.h"
#include "weapons.h"
#endif
//Don't mess with this value, unless you want to force update all maps in the game!
#ifdef RUSSIAN
#define MAJOR_MAP_VERSION 6.00
#else
#define MAJOR_MAP_VERSION 5.00
#endif
FLOAT gdMajorMapVersion = MAJOR_MAP_VERSION;
BOOLEAN gfWorldLoaded;
MAPCREATE_STRUCT gMapInformation;
//Current minor map version updater.
#define MINOR_MAP_VERSION 25
UINT8 gubMinorMapVersion = MINOR_MAP_VERSION;
/*
MINOR_MAP_VERSION Log -- Created by Kris Morness, November 14, 1997
Version 0 -- Kris -- obsolete November 14, 1997
The newly created soldier information had a couple bugs regarding initialization
Bug 1) Soldier placements without detailed slots weren't initialized.
Bug 2) The attitude variable was accidentally being generated like attributes
which usually put it completely out of range.
Version 1 -- Kris -- obsolete January 7, 1998
Bug 3) New changes to the wall decals, made the currently existing ones in the world
unpredictable, and are automatically removed, so new ones can be used.
Version 2 -- Kris -- obsolete February 3, 1998
Bug 4) Enemy mercs now have a color code assignment which defaults to army.
Version 3 -- Kris -- obsolete February 9, 1998
Bug 5) Move entry points down if they are too high.
Version 4 -- Kris -- obsolete February 25, 1998
Bug 6) Change all doors to FIRSTDOOR
Version 5 -- Kris -- obsolete March 4, 1998
Bug 7) Remove all exit grids (the format has changed)
Version 6 -- Kris -- obsolete March 9, 1998
Bug 8) Change droppable status of merc items so that they are all undroppable.
Version 7 -- Kris -- obsolete April 14, 1998
Bug 9) Priority placements have been dropped in favor of splitting it into two categories.
The first is Detailed placements, and the second is priority existance. So, all
current detailed placements will also have priority existance.
Version 8 -- Kris -- obsolete April 16, 1998
MAJOR CONFLICT RESULTING IN A MAJOR VERSION UPDATE 2.00!
Bug 10) Padding on detailed placements is uninitialized. Clear all data starting at
fKillSlotIfOwnerDies.
Version 9 -- Kris -- obsolete April 26, 1998
This version requires no auto updating, but external code has adjusted the size of the mapedgepoint
arraysize from UINT8 to UINT16. See Map Edgepoints.c.
Bug 11) Convert all wheelchaired placement bodytypes to cows. Result of change in the animation database.
Version 11 -- Kris -- obsolete May 2, 1998
Added new center entry point. Need to initialize the original padding to -1.
*/
//EntryPoints can't be placed on the top two gridnos in a map. So all we do in this case
//is return the closest gridno. Returns TRUE if the mapindex changes.
BOOLEAN ValidateEntryPointGridNo( INT16 *sGridNo )
{
INT16 sXMapPos, sYMapPos;
INT16 sWorldX, sWorldY;
INT32 iNewMapX, iNewMapY;
INT16 sTopLimit, sBottomLimit;
if( *sGridNo < 0 )
return FALSE; //entry point is non-existant
ConvertGridNoToXY( *sGridNo, &sXMapPos, &sYMapPos );
sTopLimit = 80;
sBottomLimit = gsBRY - gsTLY - 40;
//Get screen coordinates for current gridno
GetWorldXYAbsoluteScreenXY( sXMapPos, sYMapPos, &sWorldX, &sWorldY);
if( sWorldY < sTopLimit )
{
GetFromAbsoluteScreenXYWorldXY( &iNewMapX, &iNewMapY, sWorldX, sTopLimit );
}
else if( sWorldY > sBottomLimit )
{
GetFromAbsoluteScreenXYWorldXY( &iNewMapX, &iNewMapY, sWorldX, sBottomLimit );
}
else
{
return FALSE; //already valid
}
*sGridNo = (INT16)MAPROWCOLTOPOS( iNewMapY/10, iNewMapX/10 );
return TRUE; //modified
}
void SaveMapInformation( HWFILE fp )
{
UINT32 uiBytesWritten;
gMapInformation.ubMapVersion = MINOR_MAP_VERSION;
FileWrite( fp, &gMapInformation, sizeof( MAPCREATE_STRUCT ), &uiBytesWritten );
}
void LoadMapInformation( INT8 **hBuffer )
{
LOADDATA( &gMapInformation, *hBuffer, sizeof( MAPCREATE_STRUCT ) );
//FileRead( hfile, &gMapInformation, sizeof( MAPCREATE_STRUCT ), &uiBytesRead);
// ATE: OK, do some handling here for basement level scroll restrictions
// Calcuate world scrolling restrictions
InitRenderParams( gMapInformation.ubRestrictedScrollID );
}
//This will automatically update obsolete map versions to the new ones. This will even
//work in the game itself, but would require conversion to happen every time. This is completely
//transparent to the rest of the game, but in the editor, obsolete versions will be updated upon
//loading and won't be permanently updated until the map is saved, regardless of changes.
void UpdateOldVersionMap()
{
#if 0 //This code is no longer needed since the major version update from 1.0 to 4.0
//However, I am keeping it in for reference.
SOLDIERINITNODE *curr;
INT32 i;
LEVELNODE *pStruct;
//VERSION 0 -- obsolete November 14, 1997
if( gMapInformation.ubMapVersion == 0 )
{
//Soldier information contained two fixable bugs.
gMapInformation.ubMapVersion++;
curr = gSoldierInitHead;
while( curr )
{
//Bug #01) Nodes without detailed slots weren't initialized.
if( !curr->pBasicPlacement->fDetailedPlacement )
curr->pDetailedPlacement = NULL;
//Bug #02) The attitude variable was accidentally being generated like attributes
// which put it completely out of range.
if( curr->pBasicPlacement->bAttitude > 7 )
curr->pBasicPlacement->bAttitude = (INT8)Random(8);
//go to next node
curr = curr->next;
}
}
//VERSION 1 -- obsolete January 7, 1998
if( gMapInformation.ubMapVersion == 1 )
{
gMapInformation.ubMapVersion++;
//Bug #03) Removing all wall decals from map, because of new changes to the slots
// as well as certain decals found commonly in illegal places.
for( i = 0; i < WORLD_MAX; i++ )
{
RemoveAllStructsOfTypeRange( i, FIRSTWALLDECAL, LASTWALLDECAL );
RemoveAllStructsOfTypeRange( i, FIFTHWALLDECAL, SIXTHWALLDECAL );
}
}
//VERSION 2 -- obsolete February 3, 1998
if( gMapInformation.ubMapVersion == 2 )
{
gMapInformation.ubMapVersion++;
curr = gSoldierInitHead;
while( curr )
{
//Bug #04) Assign enemy mercs default army color code if applicable
if( curr->pBasicPlacement->bTeam == ENEMY_TEAM && !curr->pBasicPlacement->ubSoldierClass )
{
if( !curr->pDetailedPlacement )
{
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
}
else if( curr->pDetailedPlacement && curr->pDetailedPlacement->ubProfile == NO_PROFILE )
{
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
curr->pDetailedPlacement->ubSoldierClass = SOLDIER_CLASS_ARMY;
}
}
curr = curr->next;
}
}
//VERSION 3 -- obsolete February 9, 1998
if( gMapInformation.ubMapVersion == 3 )
{
gMapInformation.ubMapVersion++;
//Bug #05) Move entry points down if necessary.
ValidateEntryPointGridNo( &gMapInformation.sNorthGridNo );
ValidateEntryPointGridNo( &gMapInformation.sEastGridNo );
ValidateEntryPointGridNo( &gMapInformation.sSouthGridNo );
ValidateEntryPointGridNo( &gMapInformation.sWestGridNo );
}
//VERSION 4 -- obsolete February 25, 1998
if( gMapInformation.ubMapVersion == 4 )
{
gMapInformation.ubMapVersion++;
//6) Change all doors to FIRSTDOOR
for( i = 0; i < WORLD_MAX; i++ )
{
//NOTE: Here are the index values for the various doors
//DOOR OPEN CLOSED
//FIRST 916 912
//SECOND 936 932
//THIRD 956 952
//FOURTH 976 972
pStruct = gpWorldLevelData[ i ].pStructHead;
while( pStruct )
{
//outside topleft
if( pStruct->usIndex == 932 || pStruct->usIndex == 952 || pStruct->usIndex == 972 )
{
ReplaceStructIndex( i, pStruct->usIndex, 912 );
break;
}
else if( pStruct->usIndex == 936 || pStruct->usIndex == 956 || pStruct->usIndex == 976 )
{
ReplaceStructIndex( i, pStruct->usIndex, 916 );
break;
}
//outside topright
else if( pStruct->usIndex == 927 || pStruct->usIndex == 947 || pStruct->usIndex == 967 )
{
ReplaceStructIndex( i, pStruct->usIndex, 907 );
break;
}
else if( pStruct->usIndex == 931 || pStruct->usIndex == 951 || pStruct->usIndex == 971 )
{
ReplaceStructIndex( i, pStruct->usIndex, 911 );
break;
}
//inside topleft
else if( pStruct->usIndex == 942 || pStruct->usIndex == 962 || pStruct->usIndex == 982 )
{
ReplaceStructIndex( i, pStruct->usIndex, 922 );
break;
}
else if( pStruct->usIndex == 946 || pStruct->usIndex == 966 || pStruct->usIndex == 986 )
{
ReplaceStructIndex( i, pStruct->usIndex, 926 );
break;
}
//inside topright
else if( pStruct->usIndex == 937 || pStruct->usIndex == 957 || pStruct->usIndex == 977 )
{
ReplaceStructIndex( i, pStruct->usIndex, 917 );
break;
}
else if( pStruct->usIndex == 941 || pStruct->usIndex == 961 || pStruct->usIndex == 981 )
{
ReplaceStructIndex( i, pStruct->usIndex, 921 );
break;
}
pStruct = pStruct->pNext;
}
}
}
//VERSION 5 -- obsolete March 4, 1998
if( gMapInformation.ubMapVersion == 5 )
{
gMapInformation.ubMapVersion++;
//Bug 7) Remove all exit grids (the format has changed)
for( i = 0; i < WORLD_MAX; i++ )
RemoveExitGridFromWorld( i );
}
//VERSION 6 -- obsolete March 9, 1998
if( gMapInformation.ubMapVersion == 6 )
{ //Bug 8) Change droppable status of merc items so that they are all undroppable.
gMapInformation.ubMapVersion++;
curr = gSoldierInitHead;
while( curr )
{
//Bug #04) Assign enemy mercs default army color code if applicable
if( curr->pDetailedPlacement )
{
for( i = 0; i < NUM_INV_SLOTS; i++ )
{ //make all items undroppable, even if it is empty. This will allow for
//random item generation, while empty, droppable slots are locked as empty
//during random item generation.
curr->pDetailedPlacement->Inv[ i ].fFlags |= OBJECT_UNDROPPABLE;
}
}
curr = curr->next;
}
}
//VERSION 7 -- obsolete April 14, 1998
if( gMapInformation.ubMapVersion == 7 )
{
gMapInformation.ubMapVersion++;
//Bug 9) Priority placements have been dropped in favor of splitting it into two categories.
// The first is Detailed placements, and the second is priority existance. So, all
// current detailed placements will also have priority existance.
curr = gSoldierInitHead;
while( curr )
{
if( curr->pDetailedPlacement )
{
curr->pBasicPlacement->fPriorityExistance = TRUE;
}
curr = curr->next;
}
}
if( gMapInformation.ubMapVersion == 14 )
{ //Toast all of the ambiguous road pieces that ended up wrapping the byte.
LEVELNODE *pStruct, *pStruct2;
INT32 i;
for( i = 0; i < WORLD_MAX; i++ )
{
pStruct = gpWorldLevelData[ i ].pObjectHead;
if( pStruct && pStruct->usIndex == 1078 && i < WORLD_MAX-2 && i >= 320 )
{ //This is the only detectable road piece that we can repair.
pStruct2 = gpWorldLevelData[ i+1 ].pObjectHead;
if( pStruct2 && pStruct2->usIndex == 1081 )
{
RemoveObject( i, pStruct->usIndex );
RemoveObject( i+1, pStruct->usIndex+1 );
RemoveObject( i+2, pStruct->usIndex+2 );
RemoveObject( i-160, pStruct->usIndex-160 );
RemoveObject( i-159, pStruct->usIndex-159 );
RemoveObject( i-158, pStruct->usIndex-158 );
RemoveObject( i-320, pStruct->usIndex-320 );
RemoveObject( i-319, pStruct->usIndex-319 );
RemoveObject( i-318, pStruct->usIndex-318 );
AddObjectToTail( i, 1334 );
AddObjectToTail( i-160, 1335 );
AddObjectToTail( i-320, 1336 );
AddObjectToTail( i+1, 1337 );
AddObjectToTail( i-159, 1338 );
AddObjectToTail( i-319, 1339 );
AddObjectToTail( i+2, 1340 );
AddObjectToTail( i-158, 1341 );
AddObjectToTail( i-318, 1342 );
}
}
else if( pStruct && pStruct->usIndex >= 1079 && pStruct->usIndex < 1115 )
{
RemoveObject( i, pStruct->usIndex );
}
}
}
if( gMapInformation.ubMapVersion <= 7 )
{
if( gfEditMode )
{
#ifdef JA2TESTVERSION
ScreenMsg( FONT_MCOLOR_RED, MSG_ERROR, L"Currently loaded map is corrupt! Allowing the map to load anyway!" );
#endif
}
else
{
if( gbWorldSectorZ )
{
AssertMsg( 0, String( "Currently loaded map (%c%d_b%d.dat) is invalid -- less than the minimum supported version.", gWorldSectorY + 'A' - 1, gWorldSectorX, gbWorldSectorZ ) );
}
else if( !gbWorldSectorZ )
{
AssertMsg( 0, String( "Currently loaded map (%c%d.dat) is invalid -- less than the minimum supported version.", gWorldSectorY + 'A' - 1, gWorldSectorX ) );
}
}
}
//VERSION 8 -- obsolete April 18, 1998
if( gMapInformation.ubMapVersion == 8 )
{
gMapInformation.ubMapVersion++;
//Bug 10) Padding on detailed placements is uninitialized. Clear all data starting at
// fKillSlotIfOwnerDies.
curr = gSoldierInitHead;
while( curr )
{
if( curr->pDetailedPlacement )
{
//The size 120 was hand calculated. The remaining padding was 118 bytes
//and there were two one byte fields cleared, fKillSlotIfOwnerDies and ubScheduleID
memset( &curr->pDetailedPlacement->fKillSlotIfOwnerDies, 0, 120 );
}
curr = curr->next;
}
}
//Version 9 -- Kris -- obsolete April 27, 1998
if( gMapInformation.ubMapVersion == 9 )
{
gMapInformation.ubMapVersion++;
curr = gSoldierInitHead;
while( curr )
{
//Bug 11) Convert all wheelchaired placement bodytypes to cows. Result of change in the animation database.
if( curr->pDetailedPlacement && curr->pDetailedPlacement->bBodyType == CRIPPLECIV )
{
curr->pDetailedPlacement->bBodyType = COW;
curr->pBasicPlacement->bBodyType = COW;
}
curr = curr->next;
}
}
if( gMapInformation.ubMapVersion < 12 )
{
gMapInformation.ubMapVersion = 12;
gMapInformation.sCenterGridNo = -1;
}
if( gMapInformation.ubMapVersion < 13 )
{ //replace all merc ammo inventory slots status value with the max ammo that the clip can hold.
INT32 i, cnt;
OBJECTTYPE *pItem;
gMapInformation.ubMapVersion++;
//Bug 10) Padding on detailed placements is uninitialized. Clear all data starting at
// fKillSlotIfOwnerDies.
curr = gSoldierInitHead;
while( curr )
{
if( curr->pDetailedPlacement )
{
for ( i = 0; i < NUM_INV_SLOTS; i++ )
{
pItem = &curr->pDetailedPlacement->Inv[ i ];
if( Item[ pItem->usItem ].usItemClass & IC_AMMO )
{
for( cnt = 0; cnt < pItem->ubNumberOfObjects; cnt++ )
{
pItem->ubShotsLeft[ cnt ] = Magazine[ Item[ pItem->usItem ].ubClassIndex ].ubMagSize;
}
}
}
}
curr = curr->next;
}
}
if( gMapInformation.ubMapVersion < 14 )
{
gMapInformation.ubMapVersion++;
if( !gfCaves && !gfBasement )
{
ReplaceObsoleteRoads();
}
}
if( gMapInformation.ubMapVersion < 15 )
{ //Do nothing. The object layer was expanded from 1 byte to 2 bytes, effecting the
//size of the maps. This was due to the fact that the ROADPIECES tileset contains
//over 300 pieces, hence requiring a size increase of the tileset subindex for this
//layer only.
}
#endif //end of MAJOR VERSION 3.0 obsolete code
if( gMapInformation.ubMapVersion < 15 )
{
AssertMsg( 0, "Map is less than minimum supported version." );
}
if( gMapInformation.ubMapVersion < 16 )
{
gMapInformation.ubMapVersion = 16;
gMapInformation.sIsolatedGridNo = -1;
}
if( gMapInformation.ubMapVersion < 17 )
{
gMapInformation.ubMapVersion = 17;
//EliminateObjectLayerRedundancy();
}
if( gMapInformation.ubMapVersion < 18 )
{
// replace useless crowbars with proper ones
UINT32 i;
gMapInformation.ubMapVersion = 18;
for ( i = 0; i < guiNumWorldItems; i++ )
{
if ( gWorldItems[ i ].o.usItem == JAR_ELIXIR )
{
gWorldItems[ i ].o.usItem = CROWBAR;
}
}
}
if( gMapInformation.ubMapVersion < 19 )
{
//Do nothing, this is used to force regenerate the map edgepoints in map edgepoints.c
gMapInformation.ubMapVersion = 19;
}
if( gMapInformation.ubMapVersion < 20 )
{
//validate the map entry points as the world boundaries have changed.
gMapInformation.ubMapVersion = 20;
ValidateEntryPointGridNo( &gMapInformation.sNorthGridNo );
ValidateEntryPointGridNo( &gMapInformation.sEastGridNo );
ValidateEntryPointGridNo( &gMapInformation.sSouthGridNo );
ValidateEntryPointGridNo( &gMapInformation.sWestGridNo );
ValidateEntryPointGridNo( &gMapInformation.sCenterGridNo );
ValidateEntryPointGridNo( &gMapInformation.sIsolatedGridNo );
}
if( gMapInformation.ubMapVersion < 21 )
{
SOLDIERINITNODE *curr;
//override any item slots being locked if there is no item in that slot.
//Laymen terms: If any items slots are locked to be empty, make them empty but available
//for random item generation.
gMapInformation.ubMapVersion = 21;
curr = gSoldierInitHead;
while( curr )
{
if( curr->pDetailedPlacement )
{
INT32 i;
for( i = 0; i < NUM_INV_SLOTS; i++ )
{
if( !curr->pDetailedPlacement->Inv[ i ].usItem )
{
if( curr->pDetailedPlacement->Inv[ i ].fFlags & OBJECT_UNDROPPABLE )
{
if( curr->pDetailedPlacement->Inv[ i ].fFlags & OBJECT_NO_OVERWRITE )
{
curr->pDetailedPlacement->Inv[ i ].fFlags &= ~OBJECT_NO_OVERWRITE;
}
}
}
}
}
curr = curr->next;
}
}
if( gMapInformation.ubMapVersion < 22 )
{ //Allow map edgepoints to be regenerated as new system has been reenabled.
gMapInformation.ubMapVersion = 22;
}
if( gMapInformation.ubMapVersion < 23 )
{ //Allow map edgepoints to be regenerated as new system has been reenabled.
SOLDIERINITNODE *curr;
gMapInformation.ubMapVersion = 23;
if( giCurrentTilesetID == 1 ) //cave/mine tileset only
{ //convert all civilians to miners which use uniforms and more masculine body types.
curr = gSoldierInitHead;
while( curr )
{
if( curr->pBasicPlacement->bTeam == CIV_TEAM && !curr->pDetailedPlacement )
{
curr->pBasicPlacement->ubSoldierClass = SOLDIER_CLASS_MINER;
curr->pBasicPlacement->bBodyType = -1;
}
curr = curr->next;
}
}
}
if( gMapInformation.ubMapVersion < 25 )
{
gMapInformation.ubMapVersion = 25;
if( gfCaves )
{
LightSetBaseLevel( 13 );
}
}
}
void AutoCalculateItemNoOverwriteStatus()
{
SOLDIERINITNODE *curr;
INT32 i;
OBJECTTYPE *pItem;
//Recalculate the "no overwrite" status flag on all items. There are two different cases:
//1) If detailed placement has item, the item "no overwrite" flag is set
//2) If detailed placement doesn't have item, but item is set to drop (forced empty slot), the "no overwrite" flag is set.
curr = gSoldierInitHead;
while( curr )
{
if( curr->pDetailedPlacement )
{
for( i = 0; i < NUM_INV_SLOTS; i++ )
{
pItem = &curr->pDetailedPlacement->Inv[ i ];
if( pItem->usItem != NONE )
{ //case 1 (see above)
pItem->fFlags |= OBJECT_NO_OVERWRITE;
}
else if( !(pItem->fFlags & OBJECT_UNDROPPABLE) )
{ //case 2 (see above)
pItem->fFlags |= OBJECT_NO_OVERWRITE;
}
}
}
curr = curr->next;
}
}
void ValidateAndUpdateMapVersionIfNecessary()
{
//Older versions of mercs may require updating due to past bug fixes, new changes, etc.
if( gMapInformation.ubMapVersion < MINOR_MAP_VERSION )
{
SetRelativeStartAndEndPercentage( 0, 92, 93, L"Updating older map version..." );
RenderProgressBar( 0, 0 );
UpdateOldVersionMap();
}
else if( gMapInformation.ubMapVersion > MINOR_MAP_VERSION )
{
//we may have a problem...
AssertMsg( 0, "Map version is greater than the current version (old ja2.exe?)" );
}
AutoCalculateItemNoOverwriteStatus() ;
}
#ifdef JA2EDITOR
#include "Exit Grids.h"
#include "Summary Info.h"
//This function is used to avoid conflicts between minor version updates and sector summary info.
//By updating the summary info in conjunction with minor version updates, we can avoid these conflicts
//and really prevent major map updates.
void UpdateSummaryInfo( SUMMARYFILE *pSummary )
{
if( pSummary->MapInfo.ubMapVersion == MINOR_MAP_VERSION )
return;
if( pSummary->MapInfo.ubMapVersion < 9 )
{ //See bug 10
pSummary->ubCivSchedules = 0;
}
if( pSummary->MapInfo.ubMapVersion < 12 )
{
pSummary->MapInfo.sCenterGridNo = -1;
}
if( pSummary->MapInfo.ubMapVersion < 16 )
{
pSummary->MapInfo.sIsolatedGridNo = -1;
}
}
#endif
+47
View File
@@ -0,0 +1,47 @@
#ifndef __MAP_INFORMATION_H
#define __MAP_INFORMATION_H
#include "types.h"
extern FLOAT gdMajorMapVersion;
extern UINT8 gubMinorMapVersion;
enum //for use with MAPCREATE_STRUCT.ubEditorSmoothingType
{
SMOOTHING_NORMAL,
SMOOTHING_BASEMENT,
SMOOTHING_CAVES
};
typedef struct
{
//These are the mandatory entry points for a map. If any of the values are -1, then that means that
//the point has been specifically not used and that the map is not traversable to or from an adjacent
//sector in that direction. The >0 value points must be validated before saving the map. This is
//done by simply checking if those points are sittable by mercs, and that you can plot a path from
//these points to each other. These values can only be set by the editor : mapinfo tab
INT16 sNorthGridNo;
INT16 sEastGridNo;
INT16 sSouthGridNo;
INT16 sWestGridNo;
//This contains the number of individuals in the map.
//Individuals include NPCs, enemy placements, creatures, civilians, rebels, and animals.
UINT8 ubNumIndividuals;
UINT8 ubMapVersion;
UINT8 ubRestrictedScrollID;
UINT8 ubEditorSmoothingType; //normal, basement, or caves
INT16 sCenterGridNo;
INT16 sIsolatedGridNo;
INT8 bPadding[83]; //I'm sure lots of map info will be added
}MAPCREATE_STRUCT; //99 bytes
extern MAPCREATE_STRUCT gMapInformation;
void SaveMapInformation( HWFILE fp );
void LoadMapInformation( INT8 **hBuffer );
void ValidateAndUpdateMapVersionIfNecessary();
BOOLEAN ValidateEntryPointGridNo( INT16 *sGridNo );
extern BOOLEAN gfWorldLoaded;
#endif
+813
View File
@@ -0,0 +1,813 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include <stdio.h>
#include <string.h>
#include "wcheck.h"
#include "stdlib.h"
#include "debug.h"
#include "soldier control.h"
#include "weapons.h"
#include "handle items.h"
#include "worlddef.h"
#include "worldman.h"
#include "rotting corpses.h"
#include "tile cache.h"
#include "isometric utils.h"
#include "animation control.h"
#include "utilities.h"
#include "game clock.h"
#include "soldier create.h"
#include "renderworld.h"
#include "tile animation.h"
#include "merc entering.h"
#include "sound control.h"
#include "strategic.h"
#include "strategicmap.h"
#include "Handle UI.h"
#include "squads.h"
#include "english.h"
#include "cursors.h"
#include "cursor control.h"
#endif
#define MAX_MERC_IN_HELI 20
#define MAX_HELI_SCRIPT 30
#define ME_SCRIPT_DELAY 100
#define NUM_PER_HELI_RUN 6
enum
{
HELI_APPROACH,
HELI_MOVETO,
HELI_BEGINDROP,
HELI_DROP,
HELI_ENDDROP,
HELI_MOVEAWAY,
HELI_EXIT,
NUM_HELI_STATES
} HeliStateEnums;
enum
{
HELI_REST,
HELI_MOVE_DOWN,
HELI_MOVE_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_UP,
HELI_MOVEY,
HELI_MOVELARGERY,
HELI_HANDLE_DROP,
HELI_SHOW_HELI,
HELI_GOTO_BEGINDROP,
HELI_GOTO_DROP,
HELI_GOTO_EXIT,
HELI_GOTO_MOVETO,
HELI_GOTO_MOVEAWAY,
HELI_DONE,
} HeliCodes;
UINT8 ubHeliScripts[ NUM_HELI_STATES ][ MAX_HELI_SCRIPT ] =
{
// HELI_APPROACH
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_GOTO_MOVETO,
// MOVE TO
HELI_SHOW_HELI,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_MOVEY,
HELI_GOTO_BEGINDROP,
// HELI_BEGIN_DROP
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_MOVE_DOWN,
HELI_GOTO_DROP,
// Heli Begin Drop
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_UP,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_MOVESMALL_DOWN,
HELI_GOTO_DROP,
// HELI END DROP
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_MOVE_UP,
HELI_GOTO_MOVEAWAY,
// MOVE AWAY
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_MOVELARGERY,
HELI_GOTO_EXIT,
// HELI EXIT
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_REST,
HELI_DONE,
};
BOOLEAN gfHandleHeli = FALSE;
UINT8 gusHeliSeats[ MAX_MERC_IN_HELI ];
INT8 gbNumHeliSeatsOccupied = 0;
BOOLEAN gfFirstGuyDown = FALSE;
UINT32 uiSoundSample;
INT16 gsGridNoSweetSpot;
INT16 gsHeliXPos;
INT16 gsHeliYPos;
FLOAT gdHeliZPos;
INT16 gsHeliScript;
UINT8 gubHeliState;
UINT32 guiHeliLastUpdate;
INT8 gbCurDrop;
INT8 gbExitCount;
INT8 gbHeliRound;
BOOLEAN fFadingHeliIn = FALSE;
BOOLEAN fFadingHeliOut = FALSE;
BOOLEAN gfIngagedInDrop = FALSE;
ANITILE *gpHeli;
BOOLEAN gfFirstHeliRun;
void HandleFirstHeliDropOfGame( );
void ResetHeliSeats( )
{
gbNumHeliSeatsOccupied = 0;
}
void AddMercToHeli( UINT8 ubID )
{
INT32 cnt;
if ( gbNumHeliSeatsOccupied < MAX_MERC_IN_HELI )
{
// Check if it already exists!
for ( cnt = 0; cnt < gbNumHeliSeatsOccupied; cnt++ )
{
if ( gusHeliSeats[ cnt ] == ubID )
{
return;
}
}
gusHeliSeats[ gbNumHeliSeatsOccupied ] = ubID;
gbNumHeliSeatsOccupied++;
}
}
void StartHelicopterRun( INT16 sGridNoSweetSpot )
{
INT16 sX, sY;
gsGridNoSweetSpot = sGridNoSweetSpot;
if ( gbNumHeliSeatsOccupied == 0 )
{
return;
}
InterruptTime();
PauseGame();
LockPauseState( 20 );
ConvertGridNoToCenterCellXY( sGridNoSweetSpot, &sX, &sY );
gsHeliXPos = sX - ( 2 * CELL_X_SIZE );
gsHeliYPos = sY - ( 10 * CELL_Y_SIZE );
//gsHeliXPos = sX - ( 3 * CELL_X_SIZE );
//gsHeliYPos = sY + ( 4 * CELL_Y_SIZE );
gdHeliZPos = 0;
gsHeliScript = 0;
gbCurDrop = 0;
gbExitCount = 0;
gbHeliRound = 1;
gubHeliState = HELI_APPROACH;
guiHeliLastUpdate = GetJA2Clock( );
// Start sound
uiSoundSample = PlayJA2Sample( HELI_1, RATE_11025, 0, 10000, MIDDLEPAN );
fFadingHeliIn = TRUE;
gfHandleHeli = TRUE;
gfFirstGuyDown = TRUE;
guiPendingOverrideEvent = LU_BEGINUILOCK;
}
void HandleHeliDrop( )
{
UINT8 ubScriptCode;
UINT32 uiClock;
//INT16 sWorldX, sWorldY;
INT32 iVol;
INT32 cnt;
ANITILE_PARAMS AniParams;
if ( gfHandleHeli )
{
if ( gCurrentUIMode != LOCKUI_MODE )
{
guiPendingOverrideEvent = LU_BEGINUILOCK;
}
if ( _KeyDown( ESC ) )
{
// Loop through all mercs not yet placed
for ( cnt = gbCurDrop; cnt < gbNumHeliSeatsOccupied; cnt++ )
{
// Add merc to sector
MercPtrs[ gusHeliSeats[ cnt ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
UpdateMercInSector( MercPtrs[ gusHeliSeats[ cnt ] ], 9, 1, 0 );
// Check for merc arrives quotes...
HandleMercArrivesQuotes( MercPtrs[ gusHeliSeats[ cnt ] ] );
ScreenMsg( FONT_MCOLOR_WHITE, MSG_INTERFACE, TacticalStr[ MERC_HAS_ARRIVED_STR ], MercPtrs[ gusHeliSeats[ cnt ] ]->name );
}
// Remove heli
DeleteAniTile( gpHeli );
RebuildCurrentSquad( );
// Remove sound
if( uiSoundSample!=NO_SAMPLE )
{
SoundStop( uiSoundSample );
}
gfHandleHeli = FALSE;
gfIgnoreScrolling = FALSE;
gbNumHeliSeatsOccupied = 0;
UnLockPauseState();
UnPauseGame();
// Select our first guy
SelectSoldier( gusHeliSeats[ 0 ], FALSE, TRUE );
//guiCurrentEvent = LU_ENDUILOCK;
//gCurrentUIMode = LOCKUI_MODE;
guiPendingOverrideEvent = LU_ENDUILOCK;
//UIHandleLUIEndLock( NULL );
HandleFirstHeliDropOfGame( );
return;
}
gfIgnoreScrolling = TRUE;
uiClock = GetJA2Clock( );
if ( ( uiClock - guiHeliLastUpdate ) > ME_SCRIPT_DELAY )
{
guiHeliLastUpdate = uiClock;
if(fFadingHeliIn)
{
if( uiSoundSample!=NO_SAMPLE )
{
iVol=SoundGetVolume( uiSoundSample );
iVol=__min( HIGHVOLUME, iVol+5);
SoundSetVolume(uiSoundSample, iVol);
if(iVol==HIGHVOLUME)
fFadingHeliIn=FALSE;
}
else
{
fFadingHeliIn=FALSE;
}
}
else if(fFadingHeliOut)
{
if( uiSoundSample!=NO_SAMPLE )
{
iVol=SoundGetVolume(uiSoundSample);
iVol=__max( 0, iVol-5);
SoundSetVolume(uiSoundSample, iVol);
if(iVol==0)
{
// Stop sound
SoundStop( uiSoundSample );
fFadingHeliOut=FALSE;
gfHandleHeli = FALSE;
gfIgnoreScrolling = FALSE;
gbNumHeliSeatsOccupied = 0;
guiPendingOverrideEvent = LU_ENDUILOCK;
UnLockPauseState();
UnPauseGame();
RebuildCurrentSquad( );
HandleFirstHeliDropOfGame( );
}
}
else
{
fFadingHeliOut=FALSE;
gfHandleHeli = FALSE;
gfIgnoreScrolling = FALSE;
gbNumHeliSeatsOccupied = 0;
guiPendingOverrideEvent = LU_ENDUILOCK;
UnLockPauseState();
UnPauseGame();
RebuildCurrentSquad( );
HandleFirstHeliDropOfGame( );
}
}
if ( gsHeliScript == MAX_HELI_SCRIPT )
{
return;
}
ubScriptCode = ubHeliScripts[ gubHeliState ][ gsHeliScript ];
// Switch on mode...
if ( gubHeliState == HELI_DROP )
{
if ( !gfIngagedInDrop )
{
INT8 bEndVal;
bEndVal = ( gbHeliRound * NUM_PER_HELI_RUN );
if ( bEndVal > gbNumHeliSeatsOccupied )
{
bEndVal = gbNumHeliSeatsOccupied;
}
// OK, Check if we have anybody left to send!
if ( gbCurDrop < bEndVal )
{
//sWorldX = CenterX( gsGridNoSweetSpot );
//sWorldY = CenterY( gsGridNoSweetSpot );
EVENT_InitNewSoldierAnim( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], HELIDROP, 0 , FALSE );
// Change insertion code
MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
UpdateMercInSector( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], 9, 1, 0 );
//EVENT_SetSoldierPosition( MercPtrs[ gusHeliSeats[ gbCurDrop ] ], sWorldX, sWorldY );
// IF the first guy down, set squad!
if ( gfFirstGuyDown )
{
gfFirstGuyDown = FALSE;
SetCurrentSquad( MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->bAssignment, TRUE );
}
ScreenMsg( FONT_MCOLOR_WHITE, MSG_INTERFACE, TacticalStr[ MERC_HAS_ARRIVED_STR ], MercPtrs[ gusHeliSeats[ gbCurDrop ] ]->name );
gbCurDrop++;
gfIngagedInDrop = TRUE;
}
else
{
if( gbExitCount == 0 )
{
gbExitCount = 2;
}
else
{
gbExitCount--;
if ( gbExitCount == 1 )
{
// Goto leave
gsHeliScript = -1;
gubHeliState = HELI_ENDDROP;
}
}
}
}
}
switch( ubScriptCode )
{
case HELI_REST:
break;
case HELI_MOVE_DOWN:
gdHeliZPos -= 1;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVE_UP:
gdHeliZPos += 1;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVESMALL_DOWN:
gdHeliZPos -= 0.25;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVESMALL_UP:
gdHeliZPos += 0.25;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
break;
case HELI_MOVEY:
gpHeli->sRelativeY += 4;
break;
case HELI_MOVELARGERY:
gpHeli->sRelativeY += 6;
break;
case HELI_GOTO_BEGINDROP:
gsHeliScript = -1;
gubHeliState = HELI_BEGINDROP;
break;
case HELI_SHOW_HELI:
// Start animation
memset( &AniParams, 0, sizeof( ANITILE_PARAMS ) );
AniParams.sGridNo = gsGridNoSweetSpot;
AniParams.ubLevelID = ANI_SHADOW_LEVEL;
AniParams.sDelay = 90;
AniParams.sStartFrame = 0;
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_FORWARD | ANITILE_LOOPING;
AniParams.sX = gsHeliXPos;
AniParams.sY = gsHeliYPos;
AniParams.sZ = (INT16)gdHeliZPos;
strcpy( AniParams.zCachedFile, "TILECACHE\\HELI_SH.STI" );
gpHeli = CreateAnimationTile( &AniParams );
break;
case HELI_GOTO_DROP:
// Goto drop animation
gdHeliZPos -= 0.25;
gpHeli->pLevelNode->sRelativeZ = ( INT16 )gdHeliZPos;
gsHeliScript = -1;
gubHeliState = HELI_DROP;
break;
case HELI_GOTO_MOVETO:
// Goto drop animation
gsHeliScript = -1;
gubHeliState = HELI_MOVETO;
break;
case HELI_GOTO_MOVEAWAY:
// Goto drop animation
gsHeliScript = -1;
gubHeliState = HELI_MOVEAWAY;
break;
case HELI_GOTO_EXIT:
if ( gbCurDrop < gbNumHeliSeatsOccupied )
{
// Start another run......
INT16 sX, sY;
ConvertGridNoToCenterCellXY( gsGridNoSweetSpot, &sX, &sY );
gsHeliXPos = sX - ( 2 * CELL_X_SIZE );
gsHeliYPos = sY - ( 10 * CELL_Y_SIZE );
gdHeliZPos = 0;
gsHeliScript = 0;
gbExitCount = 0;
gubHeliState = HELI_APPROACH;
gbHeliRound++;
// Ahh, but still delete the heli!
DeleteAniTile( gpHeli );
gpHeli = NULL;
}
else
{
// Goto drop animation
gsHeliScript = -1;
gubHeliState = HELI_EXIT;
// Delete helicopter image!
DeleteAniTile( gpHeli );
gpHeli = NULL;
gfIgnoreScrolling = FALSE;
// Select our first guy
SelectSoldier( gusHeliSeats[ 0 ], FALSE, TRUE );
}
break;
case HELI_DONE:
// End
fFadingHeliOut = TRUE;
break;
}
gsHeliScript++;
}
}
}
void BeginMercEntering( SOLDIERTYPE *pSoldier, INT16 sGridNo )
{
ResetHeliSeats( );
AddMercToHeli( pSoldier->ubID );
StartHelicopterRun( sGridNo );
// Make sure AI does nothing.....
PauseAIUntilManuallyUnpaused();
}
void HandleFirstHeliDropOfGame( )
{
// Are we in the first heli drop?
if ( gfFirstHeliRun )
{
SyncStrategicTurnTimes();
// Call people to area
CallAvailableEnemiesTo( gsGridNoSweetSpot );
// Say quote.....
SayQuoteFromAnyBodyInSector( QUOTE_ENEMY_PRESENCE );
// Start music
SetMusicMode( MUSIC_TACTICAL_ENEMYPRESENT );
gfFirstHeliRun = FALSE;
}
// Send message to turn on ai again....
CharacterDialogueWithSpecialEvent( 0, 0, 0 , DIALOGUE_TACTICAL_UI , FALSE , FALSE , DIALOGUE_SPECIAL_EVENT_ENABLE_AI ,0, 0 );
}
+674
View File
@@ -0,0 +1,674 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "strategic.h"
#else
#include <stdio.h>
#include <string.h>
#include "wcheck.h"
#include "stdlib.h"
#include "debug.h"
#include "math.h"
#include "worlddef.h"
#include "worldman.h"
#include "renderworld.h"
#include "Assignments.h"
#include "Soldier Control.h"
#include "Animation Control.h"
#include "Animation Data.h"
#include "Isometric Utils.h"
#include "Event Pump.h"
#include "Timer Control.h"
#include "Render Fun.h"
#include "Render Dirty.h"
#include "mousesystem.h"
#include "interface.h"
#include "sysutil.h"
#include "FileMan.h"
#include "points.h"
#include "Random.h"
#include "ai.h"
#include "Interactive Tiles.h"
#include "soldier ani.h"
#include "english.h"
#include "overhead.h"
#include "Soldier Profile.h"
#include "Game Clock.h"
#include "soldier create.h"
#include "Merc Hiring.h"
#include "Game Event Hook.h"
#include "message.h"
#include "strategicmap.h"
#include "strategic.h"
#include "items.h"
#include "Soldier Add.h"
#include "History.h"
#include "Squads.h"
#include "Strategic Merc Handler.h"
#include "Dialogue Control.h"
#include "Map Screen Interface.h"
#include "Map Screen Interface Map.h"
#include "screenids.h"
#include "jascreens.h"
#include "text.h"
#include "Merc Contract.h"
#endif
#define MIN_FLIGHT_PREP_TIME 6
#ifdef JA2TESTVERSION
BOOLEAN gForceHireMerc=FALSE;
void SetFlagToForceHireMerc( BOOLEAN fForceHire );
#endif
extern BOOLEAN gfTacticalDoHeliRun;
extern BOOLEAN gfFirstHeliRun;
// ATE: Globals that dictate where the mercs will land once being hired
// Default to Omerta
// Saved in general saved game structure
INT16 gsMercArriveSectorX = 9;
INT16 gsMercArriveSectorY = 1;
void CheckForValidArrivalSector( );
INT8 HireMerc( MERC_HIRE_STRUCT *pHireMerc)
{
SOLDIERTYPE *pSoldier;
UINT8 iNewIndex;
UINT8 ubCount=0;
UINT8 ubCurrentSoldier = pHireMerc->ubProfileID;
MERCPROFILESTRUCT *pMerc;
SOLDIERCREATE_STRUCT MercCreateStruct;
BOOLEAN fReturn = FALSE;
pMerc = &gMercProfiles[ ubCurrentSoldier ];
//If we are to disregard the ststus of the merc
#ifdef JA2TESTVERSION
if( !gForceHireMerc )
#endif
//If the merc is away, Dont hire him, or if the merc is only slightly annoyed at the player
if( ( pMerc->bMercStatus != 0 ) && (pMerc->bMercStatus != MERC_ANNOYED_BUT_CAN_STILL_CONTACT ) && ( pMerc->bMercStatus != MERC_HIRED_BUT_NOT_ARRIVED_YET ) )
return( MERC_HIRE_FAILED );
if( NumberOfMercsOnPlayerTeam() >= 18 )
return( MERC_HIRE_OVER_20_MERCS_HIRED );
// ATE: if we are to use landing zone, update to latest value
// they will be updated again just before arrival...
if ( pHireMerc->fUseLandingZoneForArrival )
{
pHireMerc->sSectorX = gsMercArriveSectorX;
pHireMerc->sSectorY = gsMercArriveSectorY;
pHireMerc->bSectorZ = 0;
}
// BUILD STRUCTURES
memset( &MercCreateStruct, 0, sizeof( MercCreateStruct ) );
MercCreateStruct.ubProfile = ubCurrentSoldier;
MercCreateStruct.fPlayerMerc = TRUE;
MercCreateStruct.sSectorX = pHireMerc->sSectorX;
MercCreateStruct.sSectorY = pHireMerc->sSectorY;
MercCreateStruct.bSectorZ = pHireMerc->bSectorZ;
MercCreateStruct.bTeam = SOLDIER_CREATE_AUTO_TEAM;
MercCreateStruct.fCopyProfileItemsOver= pHireMerc->fCopyProfileItemsOver;
if ( !TacticalCreateSoldier( &MercCreateStruct, &iNewIndex ) )
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, "TacticalCreateSoldier in HireMerc(): Failed to Add Merc");
return( MERC_HIRE_FAILED );
}
if( DidGameJustStart() )
{
// OK, CHECK FOR FIRST GUY, GIVE HIM SPECIAL ITEM!
if ( iNewIndex == 0 )
{
// OK, give this item to our merc!
OBJECTTYPE Object;
// make an objecttype
memset( &Object, 0, sizeof( OBJECTTYPE ) );
Object.usItem = LETTER;
Object.ubNumberOfObjects = 1;
Object.bStatus[0] = 100;
// Give it
fReturn = AutoPlaceObject( MercPtrs[iNewIndex], &Object, FALSE );
Assert( fReturn );
}
// Set insertion for first time in chopper
// ATE: Insert for demo , not using the heli sequence....
pHireMerc->ubInsertionCode = INSERTION_CODE_CHOPPER;
}
//record how long the merc will be gone for
pMerc->bMercStatus = (UINT8)pHireMerc->iTotalContractLength;
pSoldier = &Menptr[iNewIndex];
//Copy over insertion data....
pSoldier->ubStrategicInsertionCode = pHireMerc->ubInsertionCode;
pSoldier->usStrategicInsertionData = pHireMerc->usInsertionData;
// ATE: Copy over value for using alnding zone to soldier type
pSoldier->fUseLandingZoneForArrival = pHireMerc->fUseLandingZoneForArrival;
// Set assignment
//ATE: If first time, make ON_DUTY, otherwise GUARD
if( ( pSoldier->bAssignment != IN_TRANSIT ) )
{
SetTimeOfAssignmentChangeForMerc( pSoldier );
}
ChangeSoldiersAssignment( pSoldier, IN_TRANSIT );
//set the contract length
pSoldier->iTotalContractLength = pHireMerc->iTotalContractLength;
//reset the insurance values
pSoldier->iStartOfInsuranceContract = 0;
pSoldier->iTotalLengthOfInsuranceContract = 0;
//Init the contract charge
// pSoldier->iTotalContractCharge = 0;
// store arrival time in soldier structure so map screen can display it
pSoldier->uiTimeSoldierWillArrive = pHireMerc->uiTimeTillMercArrives;
//Set the type of merc
if( DidGameJustStart() )
{
// Set time of initial merc arrival in minutes
pHireMerc->uiTimeTillMercArrives = ( STARTING_TIME + FIRST_ARRIVAL_DELAY ) / NUM_SEC_IN_MIN;
// Set insertion for first time in chopper
pHireMerc->ubInsertionCode = INSERTION_CODE_CHOPPER;
//set when the merc's contract is finished
pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 );
}
else
{
//set when the merc's contract is finished ( + 1 cause it takes a day for the merc to arrive )
pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( 1 + pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 );
}
//Set the time and ID of the last hired merc will arrive
LaptopSaveInfo.sLastHiredMerc.iIdOfMerc = pHireMerc->ubProfileID;
LaptopSaveInfo.sLastHiredMerc.uiArrivalTime = pHireMerc->uiTimeTillMercArrives;
//if we are trying to hire a merc that should arrive later, put the merc in the queue
if( pHireMerc->uiTimeTillMercArrives != 0 )
{
AddStrategicEvent( EVENT_DELAYED_HIRING_OF_MERC, pHireMerc->uiTimeTillMercArrives, pSoldier->ubID );
//specify that the merc is hired but hasnt arrived yet
pMerc->bMercStatus = MERC_HIRED_BUT_NOT_ARRIVED_YET;
}
//if the merc is an AIM merc
if( ubCurrentSoldier < 40 )
{
pSoldier->ubWhatKindOfMercAmI = MERC_TYPE__AIM_MERC;
//determine how much the contract is, and remember what type of contract he got
if( pHireMerc->iTotalContractLength == 1 )
{
//pSoldier->iTotalContractCharge = gMercProfiles[ pSoldier->ubProfile ].sSalary;
pSoldier->bTypeOfLastContract = CONTRACT_EXTEND_1_DAY;
pSoldier->iTimeCanSignElsewhere = GetWorldTotalMin();
}
else if( pHireMerc->iTotalContractLength == 7 )
{
//pSoldier->iTotalContractCharge = gMercProfiles[ pSoldier->ubProfile ].uiWeeklySalary;
pSoldier->bTypeOfLastContract = CONTRACT_EXTEND_1_WEEK;
pSoldier->iTimeCanSignElsewhere = GetWorldTotalMin();
}
else if( pHireMerc->iTotalContractLength == 14 )
{
//pSoldier->iTotalContractCharge = gMercProfiles[ pSoldier->ubProfile ].uiBiWeeklySalary;
pSoldier->bTypeOfLastContract = CONTRACT_EXTEND_2_WEEK;
// These luck fellows need to stay the whole duration!
pSoldier->iTimeCanSignElsewhere = pSoldier->iEndofContractTime;
}
// remember the medical deposit we PAID. The one in his profile can increase when he levels!
pSoldier->usMedicalDeposit = gMercProfiles[ pSoldier->ubProfile ].sMedicalDepositAmount;
}
//if the merc is from M.E.R.C.
else if( ( ubCurrentSoldier >= BIFF && ubCurrentSoldier <= BUBBA ) || ubCurrentSoldier >= GASTON )
{
pSoldier->ubWhatKindOfMercAmI = MERC_TYPE__MERC;
//pSoldier->iTotalContractCharge = -1;
gMercProfiles[ pSoldier->ubProfile ].iMercMercContractLength = 1;
//Set starting conditions for the merc
pSoldier->iStartContractTime = GetWorldDay( );
AddHistoryToPlayersLog(HISTORY_HIRED_MERC_FROM_MERC, ubCurrentSoldier, GetWorldTotalMin(), -1, -1 );
}
//If the merc is from IMP, (ie a player character)
else if( ( ubCurrentSoldier >= 51 ) && ( ubCurrentSoldier < 57 ) )
{
pSoldier->ubWhatKindOfMercAmI = MERC_TYPE__PLAYER_CHARACTER;
//pSoldier->iTotalContractCharge = -1;
}
//else its a NPC merc
else
{
pSoldier->ubWhatKindOfMercAmI = MERC_TYPE__NPC;
//pSoldier->iTotalContractCharge = -1;
}
//remove the merc from the Personnel screens departed list ( if they have never been hired before, its ok to call it )
RemoveNewlyHiredMercFromPersonnelDepartedList( pSoldier->ubProfile );
gfAtLeastOneMercWasHired = TRUE;
return( MERC_HIRE_OK );
}
void MercArrivesCallback( UINT8 ubSoldierID )
{
MERCPROFILESTRUCT *pMerc;
SOLDIERTYPE *pSoldier;
UINT32 uiTimeOfPost;
if( !DidGameJustStart() && gsMercArriveSectorX == 9 && gsMercArriveSectorY == 1 )
{ //Mercs arriving in A9. This sector has been deemed as the always safe sector.
//Seeing we don't support entry into a hostile sector (except for the beginning),
//we will nuke any enemies in this sector first.
if( gWorldSectorX != 9 || gWorldSectorY != 1 || gbWorldSectorZ )
{
EliminateAllEnemies( (UINT8)gsMercArriveSectorX, (UINT8)gsMercArriveSectorY );
}
}
// This will update ANY soldiers currently schedules to arrive too
CheckForValidArrivalSector( );
// stop time compression until player restarts it
StopTimeCompression();
pSoldier = &Menptr[ ubSoldierID ];
pMerc = &gMercProfiles[ pSoldier->ubProfile ];
// add the guy to a squad
AddCharacterToAnySquad( pSoldier );
// ATE: Make sure we use global.....
if ( pSoldier->fUseLandingZoneForArrival )
{
pSoldier->sSectorX = gsMercArriveSectorX;
pSoldier->sSectorY = gsMercArriveSectorY;
pSoldier->bSectorZ = 0;
}
// Add merc to sector ( if it's the current one )
if ( gWorldSectorX == pSoldier->sSectorX && gWorldSectorY == pSoldier->sSectorY && pSoldier->bSectorZ == gbWorldSectorZ )
{
// OK, If this sector is currently loaded, and guy does not have CHOPPER insertion code....
// ( which means we are at beginning of game if so )
// Setup chopper....
if ( pSoldier->ubStrategicInsertionCode != INSERTION_CODE_CHOPPER && pSoldier->sSectorX == 9 && pSoldier->sSectorY == 1 )
{
gfTacticalDoHeliRun = TRUE;
// OK, If we are in mapscreen, get out...
if ( guiCurrentScreen == MAP_SCREEN )
{
// ATE: Make sure the current one is selected!
ChangeSelectedMapSector( gWorldSectorX, gWorldSectorY, 0 );
RequestTriggerExitFromMapscreen( MAP_EXIT_TO_TACTICAL );
}
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_CHOPPER;
}
UpdateMercInSector( pSoldier, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
else
{
// OK, otherwise, set them in north area, so once we load again, they are here.
pSoldier->ubStrategicInsertionCode = INSERTION_CODE_NORTH;
}
if ( pSoldier->ubStrategicInsertionCode != INSERTION_CODE_CHOPPER )
{
ScreenMsg( FONT_MCOLOR_WHITE, MSG_INTERFACE, TacticalStr[ MERC_HAS_ARRIVED_STR ], pSoldier->name );
// ATE: He's going to say something, now that they've arrived...
if ( gTacticalStatus.bMercArrivingQuoteBeingUsed == FALSE && !gfFirstHeliRun )
{
gTacticalStatus.bMercArrivingQuoteBeingUsed = TRUE;
//Setup the highlight sector value (note this isn't for mines but using same system)
gsSectorLocatorX = pSoldier->sSectorX;
gsSectorLocatorY = pSoldier->sSectorY;
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, 2, 0 );
TacticalCharacterDialogue( pSoldier, QUOTE_MERC_REACHED_DESTINATION );
TacticalCharacterDialogueWithSpecialEvent( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_MINESECTOREVENT, 3, 0 );
TacticalCharacterDialogueWithSpecialEventEx( pSoldier, 0, DIALOGUE_SPECIAL_EVENT_UNSET_ARRIVES_FLAG, 0, 0, 0 );
}
}
//record how long the merc will be gone for
pMerc->bMercStatus = (UINT8)pSoldier->iTotalContractLength;
// remember when excatly he ARRIVED in Arulco, in case he gets fired early
pSoldier->uiTimeOfLastContractUpdate = GetWorldTotalMin();
//set when the merc's contract is finished
pSoldier->iEndofContractTime = GetMidnightOfFutureDayInMinutes( pSoldier->iTotalContractLength ) + ( GetHourWhenContractDone( pSoldier ) * 60 );
// Do initial check for bad items
if ( pSoldier->bTeam == gbPlayerNum )
{
//ATE: Try to see if our equipment sucks!
if ( SoldierHasWorseEquipmentThanUsedTo( pSoldier ) )
{
// Randomly anytime between 9:00, and 10:00
uiTimeOfPost = 540 + Random( 660 );
if ( GetWorldMinutesInDay() < uiTimeOfPost )
{
AddSameDayStrategicEvent( EVENT_MERC_COMPLAIN_EQUIPMENT, uiTimeOfPost , pSoldier->ubProfile );
}
}
}
HandleMercArrivesQuotes( pSoldier );
fTeamPanelDirty = TRUE;
// if the currently selected sector has no one in it, select this one instead
if ( !CanGoToTacticalInSector( sSelMapX, sSelMapY, ( UINT8 )iCurrentMapSectorZ ) )
{
ChangeSelectedMapSector( pSoldier->sSectorX, pSoldier->sSectorY, 0 );
}
return;
}
BOOLEAN IsMercHireable( UINT8 ubMercID )
{
//If the merc has an .EDT file, is not away on assignment, and isnt already hired (but not arrived yet), he is not DEAD and he isnt returning home
if( ( gMercProfiles[ ubMercID ].bMercStatus == MERC_HAS_NO_TEXT_FILE ) ||
( gMercProfiles[ ubMercID ].bMercStatus > 0 ) ||
( gMercProfiles[ ubMercID ].bMercStatus == MERC_HIRED_BUT_NOT_ARRIVED_YET ) ||
( gMercProfiles[ ubMercID ].bMercStatus == MERC_IS_DEAD ) ||
( gMercProfiles[ ubMercID ].uiDayBecomesAvailable > 0 ) ||
( gMercProfiles[ ubMercID ].bMercStatus == MERC_WORKING_ELSEWHERE ) ||
( gMercProfiles[ ubMercID ].bMercStatus == MERC_FIRED_AS_A_POW ) ||
( gMercProfiles[ ubMercID ].bMercStatus == MERC_RETURNING_HOME ) )
return(FALSE);
else
return(TRUE);
}
BOOLEAN IsMercDead( UINT8 ubMercID )
{
if( gMercProfiles[ ubMercID ].bMercStatus == MERC_IS_DEAD )
return(TRUE);
else
return(FALSE);
}
BOOLEAN IsTheSoldierAliveAndConcious( SOLDIERTYPE *pSoldier )
{
if( pSoldier->bLife >= CONSCIOUSNESS )
return(TRUE);
else
return(FALSE);
}
UINT8 NumberOfMercsOnPlayerTeam()
{
INT8 cnt;
SOLDIERTYPE *pSoldier;
INT16 bLastTeamID;
UINT8 ubCount=0;
// Set locator to first merc
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
for ( pSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pSoldier++)
{
//if the is active, and is not a vehicle
if( pSoldier->bActive && !( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) )
{
ubCount++;
}
}
return( ubCount );
}
void HandleMercArrivesQuotes( SOLDIERTYPE *pSoldier )
{
INT8 cnt, bHated, bLastTeamID;
SOLDIERTYPE *pTeamSoldier;
// If we are approaching with helicopter, don't say any ( yet )
if ( pSoldier->ubStrategicInsertionCode != INSERTION_CODE_CHOPPER )
{
// Player-generated characters issue a comment about arriving in Omerta.
if ( pSoldier->ubWhatKindOfMercAmI == MERC_TYPE__PLAYER_CHARACTER)
{
if ( gubQuest[ QUEST_DELIVER_LETTER ] == QUESTINPROGRESS )
{
TacticalCharacterDialogue( pSoldier, QUOTE_PC_DROPPED_OMERTA );
}
}
// Check to see if anyone hates this merc and will now complain
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
//loop though all the mercs
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= bLastTeamID; cnt++,pTeamSoldier++)
{
if ( pTeamSoldier->bActive )
{
if ( pTeamSoldier->ubWhatKindOfMercAmI == MERC_TYPE__AIM_MERC )
{
bHated = WhichHated( pTeamSoldier->ubProfile, pSoldier->ubProfile );
if ( bHated != -1 )
{
// hates the merc who has arrived and is going to gripe about it!
switch( bHated )
{
case 0:
TacticalCharacterDialogue( pTeamSoldier, QUOTE_HATED_1_ARRIVES );
break;
case 1:
TacticalCharacterDialogue( pTeamSoldier, QUOTE_HATED_2_ARRIVES );
break;
default:
break;
}
}
}
}
}
}
}
#ifdef JA2TESTVERSION
void SetFlagToForceHireMerc( BOOLEAN fForceHire )
{
gForceHireMerc = fForceHire;
}
#endif
UINT32 GetMercArrivalTimeOfDay( )
{
UINT32 uiCurrHour;
UINT32 uiMinHour;
// Pick a time...
// First get the current time of day.....
uiCurrHour = GetWorldHour( );
// Subtract the min time for any arrival....
uiMinHour = uiCurrHour + MIN_FLIGHT_PREP_TIME;
// OK, first check if we need to advance a whole day's time...
// See if we have missed the last flight for the day...
if ( ( uiCurrHour ) > 13 ) // ( > 1:00 pm - too bad )
{
// 7:30 flight....
return( GetMidnightOfFutureDayInMinutes( 1 ) + MERC_ARRIVE_TIME_SLOT_1 );
}
// Well, now we can handle flights all in one day....
// Find next possible flight
if ( uiMinHour <= 7 )
{
return( GetWorldDayInMinutes() + MERC_ARRIVE_TIME_SLOT_1 ); // 7:30 am
}
else if ( uiMinHour <= 13 )
{
return( GetWorldDayInMinutes() + MERC_ARRIVE_TIME_SLOT_2 ); // 1:30 pm
}
else
{
return( GetWorldDayInMinutes() + MERC_ARRIVE_TIME_SLOT_3 ); // 7:30 pm
}
}
void UpdateAnyInTransitMercsWithGlobalArrivalSector( )
{
INT32 cnt;
SOLDIERTYPE *pSoldier;
cnt = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
// look for all mercs on the same team,
for ( pSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; cnt++,pSoldier++)
{
if ( pSoldier->bActive )
{
if ( pSoldier->bAssignment == IN_TRANSIT )
{
if ( pSoldier->fUseLandingZoneForArrival )
{
pSoldier->sSectorX = gsMercArriveSectorX;
pSoldier->sSectorY = gsMercArriveSectorY;
pSoldier->bSectorZ = 0;
}
}
}
}
}
INT16 StrategicPythSpacesAway(INT16 sOrigin, INT16 sDest)
{
INT16 sRows,sCols,sResult;
sRows = abs((sOrigin / MAP_WORLD_X) - (sDest / MAP_WORLD_X));
sCols = abs((sOrigin % MAP_WORLD_X) - (sDest % MAP_WORLD_X));
// apply Pythagoras's theorem for right-handed triangle:
// dist^2 = rows^2 + cols^2, so use the square root to get the distance
sResult = (INT16)sqrt((double)(sRows * sRows) + (sCols * sCols));
return(sResult);
}
// ATE: This function will check if the current arrival sector
// is valid
// if there are enemies present, it's invalid
// if so, search around for nearest non-occupied sector.
void CheckForValidArrivalSector( )
{
INT16 sTop, sBottom;
INT16 sLeft, sRight;
INT16 cnt1, cnt2, sGoodX, sGoodY;
UINT8 ubRadius = 4;
INT32 leftmost;
INT16 sSectorGridNo, sSectorGridNo2;
INT32 uiRange, uiLowestRange = 999999;
BOOLEAN fFound = FALSE;
CHAR16 sString[ 1024 ];
CHAR16 zShortTownIDString1[ 50 ];
CHAR16 zShortTownIDString2[ 50 ];
sSectorGridNo = gsMercArriveSectorX + ( MAP_WORLD_X * gsMercArriveSectorY );
// Check if valid...
if ( !StrategicMap[ sSectorGridNo ].fEnemyControlled )
{
return;
}
GetShortSectorString( gsMercArriveSectorX ,gsMercArriveSectorY, zShortTownIDString1 );
// If here - we need to do a search!
sTop = ubRadius;
sBottom = -ubRadius;
sLeft = - ubRadius;
sRight = ubRadius;
for( cnt1 = sBottom; cnt1 <= sTop; cnt1++ )
{
leftmost = ( ( sSectorGridNo + ( MAP_WORLD_X * cnt1 ) )/ MAP_WORLD_X ) * MAP_WORLD_X;
for( cnt2 = sLeft; cnt2 <= sRight; cnt2++ )
{
sSectorGridNo2 = sSectorGridNo + ( MAP_WORLD_X * cnt1 ) + cnt2;
if( sSectorGridNo2 >=1 && sSectorGridNo2 < ( ( MAP_WORLD_X - 1 ) * ( MAP_WORLD_X - 1 ) ) && sSectorGridNo2 >= leftmost && sSectorGridNo2 < ( leftmost + MAP_WORLD_X ) )
{
if ( !StrategicMap[ sSectorGridNo2 ].fEnemyControlled && !StrategicMap[ sSectorGridNo2 ].fEnemyAirControlled )
{
uiRange = StrategicPythSpacesAway( sSectorGridNo2, sSectorGridNo );
if ( uiRange < uiLowestRange )
{
sGoodY = cnt1;
sGoodX = cnt2;
uiLowestRange = uiRange;
fFound = TRUE;
}
}
}
}
}
if ( fFound )
{
gsMercArriveSectorX = gsMercArriveSectorX + sGoodX;
gsMercArriveSectorY = gsMercArriveSectorY + sGoodY;
UpdateAnyInTransitMercsWithGlobalArrivalSector( );
GetShortSectorString( gsMercArriveSectorX ,gsMercArriveSectorY, zShortTownIDString2 );
swprintf( sString, L"Arrival of new recruits is being rerouted to sector %s, as scheduled drop-off point of sector %s is enemy occupied.", zShortTownIDString2, zShortTownIDString1 );
DoScreenIndependantMessageBox( sString, MSG_BOX_FLAG_OK, NULL );
}
}
+56
View File
@@ -0,0 +1,56 @@
#ifndef _MERC_HIRING_H_
#define _MERC_HIRING_H_
#include "Soldier Control.h"
//
// Used with the HireMerc function
//
#define MERC_HIRE_OVER_20_MERCS_HIRED -1
#define MERC_HIRE_FAILED 0
#define MERC_HIRE_OK 1
#define MERC_ARRIVE_TIME_SLOT_1 ( 7 * 60 + 30 ) // 7:30 a.m.
#define MERC_ARRIVE_TIME_SLOT_2 ( 13 * 60 + 30 ) // 1:30 pm
#define MERC_ARRIVE_TIME_SLOT_3 ( 19 * 60 + 30 ) // 7:30 pm
// ATE: This define has been moved to be a function so that
// we pick the most appropriate time of day to use...
//#define MERC_ARRIVAL_TIME_OF_DAY (7 * 60 + 30) // 7:30 am
typedef struct
{
UINT8 ubProfileID;
INT16 sSectorX;
INT16 sSectorY;
INT8 bSectorZ;
INT16 iTotalContractLength;
BOOLEAN fCopyProfileItemsOver;
UINT32 uiTimeTillMercArrives;
UINT8 ubInsertionCode;
UINT16 usInsertionData;
BOOLEAN fUseLandingZoneForArrival;
} MERC_HIRE_STRUCT;
// ATE: Globals that dictate where the mercs will land once being hired
extern INT16 gsMercArriveSectorX;
extern INT16 gsMercArriveSectorY;
INT8 HireMerc( MERC_HIRE_STRUCT *pHireMerc);
void MercArrivesCallback( UINT8 ubSoldierID );
BOOLEAN IsMercHireable( UINT8 ubMercID );
BOOLEAN IsMercDead( UINT8 ubMercID );
UINT8 NumberOfMercsOnPlayerTeam();
BOOLEAN IsTheSoldierAliveAndConcious( SOLDIERTYPE *pSoldier );
void HandleMercArrivesQuotes( SOLDIERTYPE *pSoldier );
void UpdateAnyInTransitMercsWithGlobalArrivalSector( );
UINT32 GetMercArrivalTimeOfDay( );
#endif
+130
View File
@@ -0,0 +1,130 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#include "PreBattle Interface.h"
#else
#include "Soldier Control.h"
#include "Militia Control.h"
#include "Town Militia.h"
#include "Soldier Init List.h"
#include "Campaign Types.h"
#include "Overhead.h"
#include "strategicmap.h"
#include "PreBattle Interface.h"
#endif
BOOLEAN gfStrategicMilitiaChangesMade = FALSE;
void ResetMilitia()
{
if( gfStrategicMilitiaChangesMade || gTacticalStatus.uiFlags & LOADING_SAVED_GAME )
{
gfStrategicMilitiaChangesMade = FALSE;
RemoveMilitiaFromTactical();
PrepareMilitiaForTactical();
}
}
void RemoveMilitiaFromTactical()
{
SOLDIERINITNODE *curr;
INT32 i;
for( i = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; i <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; i++ )
{
if( MercPtrs[ i ]->bActive )
{
TacticalRemoveSoldier( MercPtrs[ i ]->ubID );
}
}
curr = gSoldierInitHead;
while( curr )
{
if( curr->pBasicPlacement->bTeam == MILITIA_TEAM )
{
curr->pSoldier = NULL;
}
curr = curr->next;
}
}
void PrepareMilitiaForTactical()
{
SECTORINFO *pSector;
// INT32 i;
UINT8 ubGreen, ubRegs, ubElites;
if( gbWorldSectorZ > 0 )
return;
// Do we have a loaded sector?
if ( gWorldSectorX ==0 && gWorldSectorY == 0 )
return;
pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
ubGreen = pSector->ubNumberOfCivsAtLevel[ GREEN_MILITIA ];
ubRegs = pSector->ubNumberOfCivsAtLevel[ REGULAR_MILITIA ];
ubElites = pSector->ubNumberOfCivsAtLevel[ ELITE_MILITIA ];
AddSoldierInitListMilitia( ubGreen, ubRegs, ubElites );
/*
for( i = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID; i <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; i++ )
{
if( MercPtrs[ i ]->bInSector )
{
MercPtrs[ i ]->bAttitude = AGGRESSIVE;
}
}
*/
}
void HandleMilitiaPromotions( void )
{
UINT8 cnt;
UINT8 ubMilitiaRank;
SOLDIERTYPE * pTeamSoldier;
UINT8 ubPromotions;
gbGreenToElitePromotions = 0;
gbGreenToRegPromotions = 0;
gbRegToElitePromotions = 0;
gbMilitiaPromotions = 0;
cnt = gTacticalStatus.Team[ MILITIA_TEAM ].bFirstID;
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt <= gTacticalStatus.Team[ MILITIA_TEAM ].bLastID; cnt++, pTeamSoldier++)
{
if ( pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->bLife > 0 )
{
if ( pTeamSoldier->ubMilitiaKills > 0 )
{
ubMilitiaRank = SoldierClassToMilitiaRank( pTeamSoldier->ubSoldierClass );
ubPromotions = CheckOneMilitiaForPromotion( gWorldSectorX, gWorldSectorY, ubMilitiaRank, pTeamSoldier->ubMilitiaKills );
if( ubPromotions )
{
if( ubPromotions == 2 )
{
gbGreenToElitePromotions++;
gbMilitiaPromotions++;
}
else if( pTeamSoldier->ubSoldierClass == SOLDIER_CLASS_GREEN_MILITIA )
{
gbGreenToRegPromotions++;
gbMilitiaPromotions++;
}
else if( pTeamSoldier->ubSoldierClass == SOLDIER_CLASS_REG_MILITIA )
{
gbRegToElitePromotions++;
gbMilitiaPromotions++;
}
}
pTeamSoldier->ubMilitiaKills = 0;
}
}
}
if( gbMilitiaPromotions )
{
// ATE: Problems here with bringing up message box...
// UINT16 str[ 512 ];
// BuildMilitiaPromotionsString( str );
// DoScreenIndependantMessageBox( str, MSG_BOX_FLAG_OK, NULL );
}
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef __MILITIA_CONTROL_H
#define __MILITIA_CONTROL_H
void PrepareMilitiaForTactical();
void RemoveMilitiaFromTactical();
void ResetMilitia();
void HandleMilitiaPromotions();
extern BOOLEAN gfStrategicMilitiaChangesMade;
#endif
+966
View File
@@ -0,0 +1,966 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include <stdlib.h>
#include "Morale.h"
#include "Overhead.h"
#include "Soldier Profile.h"
#include "dialogue control.h"
#include "Map Screen Interface.h"
#include "message.h"
#include "assignments.h"
#include "Strategic Movement.h"
#include "Strategic Status.h"
#include "SkillCheck.h"
#include "drugs and alcohol.h"
#include "StrategicMap.h"
#include "Debug.h"
#endif
#define MORALE_MOD_MAX 50 // morale *mod* range is -50 to 50, if you change this, check the decay formulas!
#define DRUG_EFFECT_MORALE_MOD 150
#define ALCOHOL_EFFECT_MORALE_MOD 160
#define HOURS_BETWEEN_STRATEGIC_DECAY 3
#define PHOBIC_LIMIT -20
// macros
#define SOLDIER_IN_SECTOR( pSoldier, sX, sY, bZ ) ( !pSoldier->fBetweenSectors && ( pSoldier->sSectorX == sX ) && ( pSoldier->sSectorY == sY ) && ( pSoldier->bSectorZ == bZ ) )
MoraleEvent gbMoraleEvent[NUM_MORALE_EVENTS] =
{
// TACTICAL = Short Term Effect, STRATEGIC = Long Term Effect
{ TACTICAL_MORALE_EVENT, +4}, // MORALE_KILLED_ENEMY
{ TACTICAL_MORALE_EVENT, -5}, // MORALE_SQUADMATE_DIED, // in same sector (not really squad)... IN ADDITION to strategic loss of morale
{ TACTICAL_MORALE_EVENT, -1}, // MORALE_SUPPRESSED, // up to 4 times per turn
{ TACTICAL_MORALE_EVENT, -2}, // MORALE_AIRSTRIKE,
{ TACTICAL_MORALE_EVENT, +2}, // MORALE_DID_LOTS_OF_DAMAGE,
{ TACTICAL_MORALE_EVENT, -3}, // MORALE_TOOK_LOTS_OF_DAMAGE,
{ STRATEGIC_MORALE_EVENT, -5}, // MORALE_KILLED_CIVILIAN,
{ STRATEGIC_MORALE_EVENT, +4}, // MORALE_BATTLE_WON,
{ STRATEGIC_MORALE_EVENT, -5}, // MORALE_RAN_AWAY,
{ STRATEGIC_MORALE_EVENT, +2}, // MORALE_HEARD_BATTLE_WON,
{ STRATEGIC_MORALE_EVENT, -2}, // MORALE_HEARD_BATTLE_LOST,
{ STRATEGIC_MORALE_EVENT, +5}, // MORALE_TOWN_LIBERATED,
{ STRATEGIC_MORALE_EVENT, -5}, // MORALE_TOWN_LOST,
{ STRATEGIC_MORALE_EVENT, +8}, // MORALE_MINE_LIBERATED,
{ STRATEGIC_MORALE_EVENT, -8}, // MORALE_MINE_LOST,
{ STRATEGIC_MORALE_EVENT, +3}, // MORALE_SAM_SITE_LIBERATED,
{ STRATEGIC_MORALE_EVENT, -3}, // MORALE_SAM_SITE_LOST,
{ STRATEGIC_MORALE_EVENT, -15}, // MORALE_BUDDY_DIED,
{ STRATEGIC_MORALE_EVENT, +5}, // MORALE_HATED_DIED,
{ STRATEGIC_MORALE_EVENT, -5}, // MORALE_TEAMMATE_DIED, // not in same sector
{ STRATEGIC_MORALE_EVENT, +5}, // MORALE_LOW_DEATHRATE,
{ STRATEGIC_MORALE_EVENT, -5}, // MORALE_HIGH_DEATHRATE,
{ STRATEGIC_MORALE_EVENT, +2}, // MORALE_GREAT_MORALE,
{ STRATEGIC_MORALE_EVENT, -2}, // MORALE_POOR_MORALE,
{ TACTICAL_MORALE_EVENT, -10}, // MORALE_DRUGS_CRASH
{ TACTICAL_MORALE_EVENT, -10}, // MORALE_ALCOHOL_CRASH
{ STRATEGIC_MORALE_EVENT, +15}, // MORALE_MONSTER_QUEEN_KILLED
{ STRATEGIC_MORALE_EVENT, +25}, // MORALE_DEIDRANNA_KILLED
{ TACTICAL_MORALE_EVENT, -1}, // MORALE_CLAUSTROPHOBE_UNDERGROUND,
{ TACTICAL_MORALE_EVENT, -5}, // MORALE_INSECT_PHOBIC_SEES_CREATURE,
{ TACTICAL_MORALE_EVENT, -1}, // MORALE_NERVOUS_ALONE,
{ STRATEGIC_MORALE_EVENT, -5}, // MORALE_MERC_CAPTURED,
{ STRATEGIC_MORALE_EVENT, -5}, // MORALE_MERC_MARRIED,
{ STRATEGIC_MORALE_EVENT, +8}, // MORALE_QUEEN_BATTLE_WON,
{ STRATEGIC_MORALE_EVENT, +5}, // MORALE_SEX,
};
BOOLEAN gfSomeoneSaidMoraleQuote = FALSE;
INT8 GetMoraleModifier( SOLDIERTYPE * pSoldier )
{
if (pSoldier->uiStatusFlags & SOLDIER_PC)
{
if (pSoldier->bMorale > 50)
{
// give +1 at 55, +3 at 65, up to +5 at 95 and above
return( (pSoldier->bMorale - 45) / 10 );
}
else
{
// give penalties down to -20 at 0 (-2 at 45, -4 by 40...)
return( (pSoldier->bMorale - 50) * 2 / 5 );
}
}
else
{
// use AI morale
switch( pSoldier->bAIMorale )
{
case MORALE_HOPELESS:
return( -15 );
case MORALE_WORRIED:
return( -7 );
case MORALE_CONFIDENT:
return( 2 );
case MORALE_FEARLESS:
return( 5 );
default:
return( 0 );
}
}
}
void DecayTacticalMorale( SOLDIERTYPE * pSoldier )
{
// decay the tactical morale modifier
if (pSoldier->bTacticalMoraleMod != 0)
{
// decay the modifier!
if (pSoldier->bTacticalMoraleMod > 0)
{
pSoldier->bTacticalMoraleMod = __max( 0, pSoldier->bTacticalMoraleMod - (8 - pSoldier->bTacticalMoraleMod / 10) );
}
else
{
pSoldier->bTacticalMoraleMod = __min( 0, pSoldier->bTacticalMoraleMod + (6 + pSoldier->bTacticalMoraleMod / 10) );
}
}
}
void DecayStrategicMorale( SOLDIERTYPE * pSoldier )
{
// decay the modifier!
if (pSoldier->bStrategicMoraleMod > 0)
{
pSoldier->bStrategicMoraleMod = __max( 0, pSoldier->bStrategicMoraleMod - (8 - pSoldier->bStrategicMoraleMod / 10) );
}
else
{
pSoldier->bStrategicMoraleMod = __min( 0, pSoldier->bStrategicMoraleMod + (6 + pSoldier->bStrategicMoraleMod / 10) );
}
}
void DecayTacticalMoraleModifiers( void )
{
SOLDIERTYPE * pSoldier;
UINT8 ubLoop, ubLoop2;
BOOLEAN fHandleNervous;
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pSoldier++ )
{
//if the merc is active, in Arulco
// CJC: decay modifiers while asleep! or POW!
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE &&
!(pSoldier->bAssignment == IN_TRANSIT ||
pSoldier->bAssignment == ASSIGNMENT_DEAD ) )
{
// only let morale mod decay if it is positive while merc is a POW
if ( pSoldier->bAssignment == ASSIGNMENT_POW && pSoldier->bTacticalMoraleMod < 0 )
{
continue;
}
switch( gMercProfiles[ pSoldier->ubProfile ].bPersonalityTrait )
{
case CLAUSTROPHOBIC:
if ( pSoldier->bSectorZ > 0 )
{
// underground, no recovery... in fact, if tact morale is high, decay
if ( pSoldier->bTacticalMoraleMod > PHOBIC_LIMIT )
{
HandleMoraleEvent( pSoldier, MORALE_CLAUSTROPHOBE_UNDERGROUND, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
continue;
}
break;
case NERVOUS:
if ( pSoldier->bMorale < 50 )
{
if (pSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pSoldier->ubGroupID ))
{
if ( NumberOfPeopleInSquad( pSoldier->bAssignment ) == 1 )
{
fHandleNervous = TRUE;
}
else
{
fHandleNervous = FALSE;
}
}
else if ( pSoldier->bActive && pSoldier->bInSector )
{
if ( DistanceToClosestFriend( pSoldier ) > NERVOUS_RADIUS )
{
fHandleNervous = TRUE;
}
else
{
fHandleNervous = FALSE;
}
}
else
{
// look for anyone else in same sector
fHandleNervous = TRUE;
for ( ubLoop2 = gTacticalStatus.Team[ gbPlayerNum ].bFirstID; ubLoop2 <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop2++ )
{
if ( MercPtrs[ ubLoop2 ] != pSoldier && MercPtrs[ ubLoop2 ]->bActive && MercPtrs[ ubLoop2 ]->sSectorX == pSoldier->sSectorX && MercPtrs[ ubLoop2 ]->sSectorY == pSoldier->sSectorY && MercPtrs[ ubLoop2 ]->bSectorZ == pSoldier->bSectorZ )
{
// found someone!
fHandleNervous = FALSE;
break;
}
}
}
if ( fHandleNervous )
{
if ( pSoldier->bTacticalMoraleMod == PHOBIC_LIMIT )
{
// don't change morale
continue;
}
// alone, no recovery... in fact, if tact morale is high, decay
if ( !(pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_PERSONALITY) )
{
TacticalCharacterDialogue( pSoldier, QUOTE_PERSONALITY_TRAIT );
pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_PERSONALITY;
}
HandleMoraleEvent( pSoldier, MORALE_NERVOUS_ALONE, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
continue;
}
}
}
DecayTacticalMorale( pSoldier );
RefreshSoldierMorale( pSoldier );
}
}
}
void DecayStrategicMoraleModifiers( void )
{
SOLDIERTYPE * pSoldier;
UINT8 ubLoop;
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pSoldier++ )
{
//if the merc is active, in Arulco
// CJC: decay modifiers while asleep! or POW!
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE &&
!(pSoldier->bAssignment == IN_TRANSIT ||
pSoldier->bAssignment == ASSIGNMENT_DEAD ) )
{
// only let morale mod decay if it is positive while merc is a POW
if ( pSoldier->bAssignment == ASSIGNMENT_POW && pSoldier->bStrategicMoraleMod < 0 )
{
continue;
}
DecayStrategicMorale( pSoldier );
RefreshSoldierMorale( pSoldier );
}
}
}
void RefreshSoldierMorale( SOLDIERTYPE * pSoldier )
{
INT32 iActualMorale;
if ( pSoldier->fMercAsleep )
{
// delay this till later!
return;
}
// CJC, April 19, 1999: added up to 20% morale boost according to progress
iActualMorale = DEFAULT_MORALE + (INT32) pSoldier->bTeamMoraleMod + (INT32) pSoldier->bTacticalMoraleMod + (INT32) pSoldier->bStrategicMoraleMod + (INT32) (CurrentPlayerProgressPercentage() / 5);
// ATE: Modify morale based on drugs....
iActualMorale += ( ( pSoldier->bDrugEffect[ DRUG_TYPE_ADRENALINE ] * DRUG_EFFECT_MORALE_MOD ) / 100 );
iActualMorale += ( ( pSoldier->bDrugEffect[ DRUG_TYPE_ALCOHOL ] * ALCOHOL_EFFECT_MORALE_MOD ) / 100 );
iActualMorale = __min( 100, iActualMorale );
iActualMorale = __max( 0, iActualMorale );
pSoldier->bMorale = (INT8) iActualMorale;
// update mapscreen as needed
fCharacterInfoPanelDirty = TRUE;
}
void UpdateSoldierMorale( SOLDIERTYPE * pSoldier, UINT8 ubType, INT8 bMoraleMod )
{
MERCPROFILESTRUCT * pProfile;
INT32 iMoraleModTotal;
if ( !pSoldier->bActive || ( pSoldier->bLife < CONSCIOUSNESS ) ||
( pSoldier->uiStatusFlags & SOLDIER_VEHICLE ) || AM_A_ROBOT( pSoldier ) || AM_AN_EPC( pSoldier ) )
{
return;
}
if ( ( pSoldier->bAssignment == ASSIGNMENT_DEAD ) ||
( pSoldier->bAssignment == ASSIGNMENT_POW ) ||
( pSoldier->bAssignment == IN_TRANSIT ) )
{
return;
}
if ( pSoldier->ubProfile == NO_PROFILE )
{
return;
}
pProfile = &(gMercProfiles[ pSoldier->ubProfile ]);
if (bMoraleMod > 0)
{
switch( pProfile->bAttitude )
{
case ATT_OPTIMIST:
case ATT_AGGRESSIVE:
bMoraleMod += 1;
break;
case ATT_PESSIMIST:
bMoraleMod -= 1;
break;
default:
break;
}
if (bMoraleMod < 0)
{
// can't change a positive event into a negative one!
bMoraleMod = 0;
}
}
else
{
switch( pProfile->bAttitude )
{
case ATT_OPTIMIST:
bMoraleMod += 1;
break;
case ATT_PESSIMIST:
bMoraleMod -= 1;
break;
case ATT_COWARD:
bMoraleMod -= 2;
default:
break;
}
if (pSoldier->bLevel == 1)
{
bMoraleMod--;
}
else if (pSoldier->bLevel > 5)
{
bMoraleMod++;
}
if (bMoraleMod > 0)
{
// can't change a negative event into a positive one!
bMoraleMod = 0;
}
}
// apply change!
if (ubType == TACTICAL_MORALE_EVENT)
{
iMoraleModTotal = (INT32) pSoldier->bTacticalMoraleMod + (INT32) bMoraleMod;
iMoraleModTotal = __min( iMoraleModTotal, MORALE_MOD_MAX );
iMoraleModTotal = __max( iMoraleModTotal, -MORALE_MOD_MAX );
pSoldier->bTacticalMoraleMod = (INT8) iMoraleModTotal;
}
else if ( gTacticalStatus.fEnemyInSector && !pSoldier->bInSector ) // delayed strategic
{
iMoraleModTotal = (INT32) pSoldier->bDelayedStrategicMoraleMod + (INT32) bMoraleMod;
iMoraleModTotal = __min( iMoraleModTotal, MORALE_MOD_MAX );
iMoraleModTotal = __max( iMoraleModTotal, -MORALE_MOD_MAX );
pSoldier->bDelayedStrategicMoraleMod = (INT8) iMoraleModTotal;
}
else // strategic
{
iMoraleModTotal = (INT32) pSoldier->bStrategicMoraleMod + (INT32) bMoraleMod;
iMoraleModTotal = __min( iMoraleModTotal, MORALE_MOD_MAX );
iMoraleModTotal = __max( iMoraleModTotal, -MORALE_MOD_MAX );
pSoldier->bStrategicMoraleMod = (INT8) iMoraleModTotal;
}
RefreshSoldierMorale( pSoldier );
if ( !pSoldier->fMercAsleep )
{
if ( !gfSomeoneSaidMoraleQuote )
{
// Check if we're below a certain value and warn
if ( pSoldier->bMorale < 35 )
{
// Have we said this quote yet?
if ( !( pSoldier->usQuoteSaidFlags & SOLDIER_QUOTE_SAID_LOW_MORAL ) )
{
gfSomeoneSaidMoraleQuote = TRUE;
// ATE: Amde it a DELAYED QUOTE - will be delayed by the dialogue Q until it's our turn...
DelayedTacticalCharacterDialogue( pSoldier, QUOTE_STARTING_TO_WHINE );
pSoldier->usQuoteSaidFlags |= SOLDIER_QUOTE_SAID_LOW_MORAL;
}
}
}
}
// Reset flag!
if ( pSoldier->bMorale > 65 )
{
pSoldier->usQuoteSaidFlags &= (~SOLDIER_QUOTE_SAID_LOW_MORAL );
}
}
void HandleMoraleEventForSoldier( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent )
{
UpdateSoldierMorale( pSoldier, gbMoraleEvent[bMoraleEvent].ubType, gbMoraleEvent[bMoraleEvent].bChange );
}
void HandleMoraleEvent( SOLDIERTYPE *pSoldier, INT8 bMoraleEvent, INT16 sMapX, INT16 sMapY, INT8 bMapZ )
{
UINT8 ubLoop;
SOLDIERTYPE * pTeamSoldier;
MERCPROFILESTRUCT * pProfile;
gfSomeoneSaidMoraleQuote = FALSE;
// NOTE: Many morale events are NOT attached to a specific player soldier at all!
// Those that do need it have Asserts on a case by case basis below
if (pSoldier == NULL)
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Handling morale event %d at X=%d, Y=%d,Z=%d", bMoraleEvent, sMapX, sMapY, bMapZ ) );
}
else
{
DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String( "Handling morale event %d for %S at X=%d, Y=%d, Z=%d", bMoraleEvent, pSoldier->name, sMapX, sMapY, bMapZ ) );
}
switch( bMoraleEvent )
{
case MORALE_KILLED_ENEMY:
case MORALE_DID_LOTS_OF_DAMAGE:
case MORALE_DRUGS_CRASH:
case MORALE_ALCOHOL_CRASH:
case MORALE_SUPPRESSED:
case MORALE_TOOK_LOTS_OF_DAMAGE:
case MORALE_HIGH_DEATHRATE:
case MORALE_SEX:
// needs specific soldier!
Assert( pSoldier );
// affects the soldier only
HandleMoraleEventForSoldier( pSoldier, bMoraleEvent );
break;
case MORALE_CLAUSTROPHOBE_UNDERGROUND:
case MORALE_INSECT_PHOBIC_SEES_CREATURE:
case MORALE_NERVOUS_ALONE:
// needs specific soldier!
Assert( pSoldier );
// affects the soldier only, should be ignored if tactical morale mod is -20 or less
if ( pSoldier->bTacticalMoraleMod > PHOBIC_LIMIT )
{
HandleMoraleEventForSoldier( pSoldier, bMoraleEvent );
}
break;
case MORALE_BATTLE_WON:
// affects everyone to varying degrees
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive )
{
if ( SOLDIER_IN_SECTOR( pTeamSoldier, sMapX, sMapY, bMapZ ) )
{
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_BATTLE_WON );
}
else
{
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_HEARD_BATTLE_WON );
}
}
}
break;
case MORALE_RAN_AWAY:
// affects everyone to varying degrees
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive )
{
// CJC: adding to SOLDIER_IN_SECTOR check special stuff because the old sector values might
// be appropriate (because in transit going out of that sector!)
if ( SOLDIER_IN_SECTOR( pTeamSoldier, sMapX, sMapY, bMapZ ) || ( pTeamSoldier->fBetweenSectors && ((pTeamSoldier->ubPrevSectorID % 16) + 1) == sMapX && ((pTeamSoldier->ubPrevSectorID / 16) + 1) == sMapY && ( pTeamSoldier->bSectorZ == bMapZ ) ) )
{
switch ( gMercProfiles[ pTeamSoldier->ubProfile ].bAttitude )
{
case ATT_AGGRESSIVE:
// double the penalty - these guys REALLY hate running away
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_RAN_AWAY );
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_RAN_AWAY );
break;
case ATT_COWARD:
// no penalty - cowards are perfectly happy to avoid fights!
break;
default:
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_RAN_AWAY );
break;
}
}
else
{
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_HEARD_BATTLE_LOST );
}
}
}
break;
case MORALE_TOWN_LIBERATED:
case MORALE_TOWN_LOST:
case MORALE_MINE_LIBERATED:
case MORALE_MINE_LOST:
case MORALE_SAM_SITE_LIBERATED:
case MORALE_SAM_SITE_LOST:
case MORALE_KILLED_CIVILIAN:
case MORALE_LOW_DEATHRATE:
case MORALE_HEARD_BATTLE_WON:
case MORALE_HEARD_BATTLE_LOST:
case MORALE_MONSTER_QUEEN_KILLED:
case MORALE_DEIDRANNA_KILLED:
// affects everyone, everywhere
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive )
{
HandleMoraleEventForSoldier( pTeamSoldier, bMoraleEvent );
}
}
break;
case MORALE_POOR_MORALE:
case MORALE_GREAT_MORALE:
case MORALE_AIRSTRIKE:
// affects every in sector
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive && SOLDIER_IN_SECTOR( pTeamSoldier, sMapX, sMapY, bMapZ ) )
{
HandleMoraleEventForSoldier( pTeamSoldier, bMoraleEvent );
}
}
break;
case MORALE_MERC_CAPTURED:
// needs specific soldier! (for reputation, not here)
Assert( pSoldier );
// affects everyone
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive )
{
HandleMoraleEventForSoldier( pTeamSoldier, bMoraleEvent );
}
}
break;
case MORALE_TEAMMATE_DIED:
// needs specific soldier!
Assert( pSoldier );
// affects everyone, in sector differently than not, extra bonuses if it's a buddy or hated merc
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE)
{
pProfile = &(gMercProfiles[ pTeamSoldier->ubProfile ]);
if (HATED_MERC( pProfile, pSoldier->ubProfile ))
{
// yesss!
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_HATED_DIED );
}
else
{
if ( SOLDIER_IN_SECTOR( pTeamSoldier, sMapX, sMapY, bMapZ ) )
{
// mate died in my sector! tactical morale mod
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_SQUADMATE_DIED );
}
// this is handled for everyone even if in sector, as it's a strategic morale mod
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_TEAMMATE_DIED );
if (BUDDY_MERC( pProfile, pSoldier->ubProfile ))
{
// oh no! buddy died!
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_BUDDY_DIED );
}
}
}
}
break;
case MORALE_MERC_MARRIED:
// female mercs get unhappy based on how sexist they are (=hate men)
// gentlemen males get unhappy too
ubLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ ubLoop ]; ubLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; ubLoop++, pTeamSoldier++ )
{
if ( pTeamSoldier->bActive && pTeamSoldier->ubProfile != NO_PROFILE )
{
if ( WhichHated( pTeamSoldier->ubProfile, pSoldier->ubProfile ) != -1 )
{
// we hate 'em anyways
continue;
}
if ( gMercProfiles[ pTeamSoldier->ubProfile ].bSex == FEMALE )
{
switch( gMercProfiles[ pTeamSoldier->ubProfile ].bSexist )
{
case SOMEWHAT_SEXIST:
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_MERC_MARRIED );
break;
case VERY_SEXIST:
// handle TWICE!
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_MERC_MARRIED );
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_MERC_MARRIED );
break;
default:
break;
}
}
else
{
switch( gMercProfiles[ pTeamSoldier->ubProfile ].bSexist )
{
case GENTLEMAN:
HandleMoraleEventForSoldier( pTeamSoldier, MORALE_MERC_MARRIED );
break;
default:
break;
}
}
}
}
break;
default:
// debug message
ScreenMsg( MSG_FONT_RED, MSG_BETAVERSION, L"Invalid morale event type = %d. AM/CC-1", bMoraleEvent );
break;
}
// some morale events also impact the player's reputation with the mercs back home
switch( bMoraleEvent )
{
case MORALE_HIGH_DEATHRATE:
ModifyPlayerReputation(REPUTATION_HIGH_DEATHRATE);
break;
case MORALE_LOW_DEATHRATE:
ModifyPlayerReputation(REPUTATION_LOW_DEATHRATE);
break;
case MORALE_POOR_MORALE:
ModifyPlayerReputation(REPUTATION_POOR_MORALE);
break;
case MORALE_GREAT_MORALE:
ModifyPlayerReputation(REPUTATION_GREAT_MORALE);
break;
case MORALE_BATTLE_WON:
ModifyPlayerReputation(REPUTATION_BATTLE_WON);
break;
case MORALE_RAN_AWAY:
case MORALE_HEARD_BATTLE_LOST:
ModifyPlayerReputation(REPUTATION_BATTLE_LOST);
break;
case MORALE_TOWN_LIBERATED:
ModifyPlayerReputation(REPUTATION_TOWN_WON);
break;
case MORALE_TOWN_LOST:
ModifyPlayerReputation(REPUTATION_TOWN_LOST);
break;
case MORALE_TEAMMATE_DIED:
// impact depends on that dude's level of experience
ModifyPlayerReputation((UINT8) (pSoldier->bExpLevel * REPUTATION_SOLDIER_DIED));
break;
case MORALE_MERC_CAPTURED:
// impact depends on that dude's level of experience
ModifyPlayerReputation((UINT8) (pSoldier->bExpLevel * REPUTATION_SOLDIER_CAPTURED));
break;
case MORALE_KILLED_CIVILIAN:
ModifyPlayerReputation(REPUTATION_KILLED_CIVILIAN);
break;
case MORALE_MONSTER_QUEEN_KILLED:
ModifyPlayerReputation(REPUTATION_KILLED_MONSTER_QUEEN);
break;
case MORALE_DEIDRANNA_KILLED:
ModifyPlayerReputation(REPUTATION_KILLED_DEIDRANNA);
break;
default:
// no reputation impact
break;
}
}
void HourlyMoraleUpdate( void )
{
INT8 bMercID, bOtherID;
INT8 bActualTeamOpinion;
INT8 bTeamMoraleModChange, bTeamMoraleModDiff;
INT8 bOpinion=-1;
INT32 iTotalOpinions;
INT8 bNumTeamMembers;
INT8 bHighestTeamLeadership = 0;
INT8 bLastTeamID;
SOLDIERTYPE * pSoldier;
SOLDIERTYPE * pOtherSoldier;
MERCPROFILESTRUCT * pProfile;
BOOLEAN fSameGroupOnly;
static INT8 bStrategicMoraleUpdateCounter = 0;
BOOLEAN fFoundHated = FALSE;
INT8 bHated;
bMercID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
bLastTeamID = gTacticalStatus.Team[ gbPlayerNum ].bLastID;
// loop through all mercs to calculate their morale
for ( pSoldier = MercPtrs[ bMercID ]; bMercID <= bLastTeamID; bMercID++,pSoldier++)
{
//if the merc is active, in Arulco, and conscious, not POW
if ( pSoldier->bActive && pSoldier->ubProfile != NO_PROFILE &&
!(pSoldier->bAssignment == IN_TRANSIT ||
pSoldier->fMercAsleep == TRUE ||
pSoldier->bAssignment == ASSIGNMENT_DEAD ||
pSoldier->bAssignment == ASSIGNMENT_POW) )
{
// calculate the guy's opinion of the people he is with
pProfile = &(gMercProfiles[ pSoldier->ubProfile ]);
// if we're moving
if (pSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pSoldier->ubGroupID ))
{
// we only check our opinions of people in our squad
fSameGroupOnly = TRUE;
}
else
{
fSameGroupOnly = FALSE;
}
fFoundHated = FALSE;
// reset counts to calculate average opinion
iTotalOpinions = 0;
bNumTeamMembers = 0;
// let people with high leadership affect their own morale
bHighestTeamLeadership = EffectiveLeadership( pSoldier );
// loop through all other mercs
bOtherID = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pOtherSoldier = MercPtrs[ bOtherID ]; bOtherID <= bLastTeamID; bOtherID++,pOtherSoldier++)
{
// skip past ourselves and all inactive mercs
if (bOtherID != bMercID && pOtherSoldier->bActive && pOtherSoldier->ubProfile != NO_PROFILE &&
!(pOtherSoldier->bAssignment == IN_TRANSIT ||
pOtherSoldier->fMercAsleep == TRUE ||
pOtherSoldier->bAssignment == ASSIGNMENT_DEAD ||
pOtherSoldier->bAssignment == ASSIGNMENT_POW))
{
if (fSameGroupOnly)
{
// all we have to check is the group ID
if (pSoldier->ubGroupID != pOtherSoldier->ubGroupID)
{
continue;
}
}
else
{
// check to see if the location is the same
if (pOtherSoldier->sSectorX != pSoldier->sSectorX ||
pOtherSoldier->sSectorY != pSoldier->sSectorY ||
pOtherSoldier->bSectorZ != pSoldier->bSectorZ)
{
continue;
}
// if the OTHER soldier is in motion then we don't do anything!
if (pOtherSoldier->ubGroupID != 0 && PlayerIDGroupInMotion( pOtherSoldier->ubGroupID ))
{
continue;
}
}
bOpinion = pProfile->bMercOpinion[ pOtherSoldier->ubProfile ];
if (bOpinion == HATED_OPINION)
{
bHated = WhichHated( pSoldier->ubProfile, pOtherSoldier->ubProfile );
if ( bHated >= 2 )
{
// learn to hate which has become full-blown hatred, full strength
fFoundHated = TRUE;
break;
}
else
{
// scale according to how close to we are to snapping
//KM : Divide by 0 error found. Wrapped into an if statement.
if( pProfile->bHatedTime[ bHated ] )
{
bOpinion = ((INT32) bOpinion) * (pProfile->bHatedTime[ bHated ] - pProfile->bHatedCount[ bHated ]) / pProfile->bHatedTime[ bHated ];
}
if ( pProfile->bHatedCount[ bHated ] <= pProfile->bHatedTime[ bHated ] / 2 )
{
// Augh, we're teamed with someone we hate! We HATE this!! Ignore everyone else!
fFoundHated = TRUE;
break;
}
// otherwise just mix this opinion in with everyone else...
}
}
iTotalOpinions += bOpinion;
bNumTeamMembers++;
if ( EffectiveLeadership( pOtherSoldier ) > bHighestTeamLeadership)
{
bHighestTeamLeadership = EffectiveLeadership( pOtherSoldier );
}
}
}
if (fFoundHated)
{
// If teamed with someone we hated, team opinion is automatically minimum
bActualTeamOpinion = HATED_OPINION;
}
else if (bNumTeamMembers > 0)
{
bActualTeamOpinion = (INT8) (iTotalOpinions / bNumTeamMembers);
// give bonus/penalty for highest leadership value on team
bActualTeamOpinion += (bHighestTeamLeadership - 50) / 10;
}
else // alone
{
bActualTeamOpinion = 0;
}
// reduce to a range of HATED through BUDDY
if (bActualTeamOpinion > BUDDY_OPINION)
{
bActualTeamOpinion = BUDDY_OPINION;
}
else if (bActualTeamOpinion < HATED_OPINION)
{
bActualTeamOpinion = HATED_OPINION;
}
// shift morale from team by ~10%
// this should range between -75 and +75
bTeamMoraleModDiff = bActualTeamOpinion - pSoldier->bTeamMoraleMod;
if (bTeamMoraleModDiff > 0)
{
bTeamMoraleModChange = 1 + bTeamMoraleModDiff / 10;
}
else if (bTeamMoraleModDiff < 0)
{
bTeamMoraleModChange = -1 + bTeamMoraleModDiff / 10;
}
else
{
bTeamMoraleModChange = 0;
}
pSoldier->bTeamMoraleMod += bTeamMoraleModChange;
pSoldier->bTeamMoraleMod = __min( pSoldier->bTeamMoraleMod, MORALE_MOD_MAX );
pSoldier->bTeamMoraleMod = __max( pSoldier->bTeamMoraleMod, -MORALE_MOD_MAX );
// New, December 3rd, 1998, by CJC --
// If delayed strategic modifier exists then incorporate it in strategic mod
if ( pSoldier->bDelayedStrategicMoraleMod )
{
pSoldier->bStrategicMoraleMod += pSoldier->bDelayedStrategicMoraleMod;
pSoldier->bDelayedStrategicMoraleMod = 0;
pSoldier->bStrategicMoraleMod = __min( pSoldier->bStrategicMoraleMod, MORALE_MOD_MAX );
pSoldier->bStrategicMoraleMod = __max( pSoldier->bStrategicMoraleMod, -MORALE_MOD_MAX );
}
// refresh the morale value for the soldier based on the recalculated team modifier
RefreshSoldierMorale( pSoldier );
}
}
bStrategicMoraleUpdateCounter++;
if ( bStrategicMoraleUpdateCounter == HOURS_BETWEEN_STRATEGIC_DECAY )
{
DecayStrategicMoraleModifiers();
bStrategicMoraleUpdateCounter = 0;
}
}
void DailyMoraleUpdate(SOLDIERTYPE *pSoldier)
{
if ( pSoldier->ubProfile == NO_PROFILE )
{
return;
}
// CJC: made per hour now
/*
// decay the merc's strategic morale modifier
if (pSoldier->bStrategicMoraleMod != 0)
{
// decay the modifier!
DecayStrategicMorale( pSoldier );
// refresh the morale value for the soldier based on the recalculated modifier
RefreshSoldierMorale( pSoldier );
}
*/
// check death rate vs. merc's tolerance once/day (ignores buddies!)
if ( MercThinksDeathRateTooHigh( pSoldier->ubProfile ) )
{
// too high, morale takes a hit
HandleMoraleEvent( pSoldier, MORALE_HIGH_DEATHRATE, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
// check his morale vs. his morale tolerance once/day (ignores buddies!)
if ( MercThinksHisMoraleIsTooLow( pSoldier ) )
{
// too low, morale sinks further (merc's in a funk and things aren't getting better)
HandleMoraleEvent( pSoldier, MORALE_POOR_MORALE, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
else if ( pSoldier->bMorale >= 75 )
{
// very high morale, merc is cheerleading others
HandleMoraleEvent( pSoldier, MORALE_GREAT_MORALE, pSoldier->sSectorX, pSoldier->sSectorY, pSoldier->bSectorZ );
}
}
+71
View File
@@ -0,0 +1,71 @@
#ifndef _MORALE_H
#define _MORALE_H
#include "Types.h"
#include "Soldier Control.h"
#define DEFAULT_MORALE 50
typedef enum
{
MORALE_KILLED_ENEMY = 0,
MORALE_SQUADMATE_DIED,
MORALE_SUPPRESSED,
MORALE_AIRSTRIKE,
MORALE_DID_LOTS_OF_DAMAGE,
MORALE_TOOK_LOTS_OF_DAMAGE, // 5
MORALE_KILLED_CIVILIAN,
MORALE_BATTLE_WON,
MORALE_RAN_AWAY,
MORALE_HEARD_BATTLE_WON,
MORALE_HEARD_BATTLE_LOST, // 10
MORALE_TOWN_LIBERATED,
MORALE_TOWN_LOST,
MORALE_MINE_LIBERATED,
MORALE_MINE_LOST,
MORALE_SAM_SITE_LIBERATED, // 15
MORALE_SAM_SITE_LOST,
MORALE_BUDDY_DIED,
MORALE_HATED_DIED,
MORALE_TEAMMATE_DIED,
MORALE_LOW_DEATHRATE, // 20
MORALE_HIGH_DEATHRATE,
MORALE_GREAT_MORALE,
MORALE_POOR_MORALE,
MORALE_DRUGS_CRASH,
MORALE_ALCOHOL_CRASH, // 25
MORALE_MONSTER_QUEEN_KILLED,
MORALE_DEIDRANNA_KILLED,
MORALE_CLAUSTROPHOBE_UNDERGROUND,
MORALE_INSECT_PHOBIC_SEES_CREATURE,
MORALE_NERVOUS_ALONE, // 30
MORALE_MERC_CAPTURED,
MORALE_MERC_MARRIED,
MORALE_QUEEN_BATTLE_WON,
MORALE_SEX,
NUM_MORALE_EVENTS
} MoraleEventNames;
typedef enum
{
TACTICAL_MORALE_EVENT = 0,
STRATEGIC_MORALE_EVENT
} MoraleEventType;
typedef struct MoraleEvent
{
UINT8 ubType;
INT8 bChange;
} MoraleEvent;
extern void HandleMoraleEvent( SOLDIERTYPE * pSoldier, INT8 bMoraleEvent, INT16 sMapX, INT16 sMapY, INT8 bMapZ );
extern void RefreshSoldierMorale( SOLDIERTYPE * pSoldier );
extern INT8 GetMoraleModifier( SOLDIERTYPE * pSoldier );
void HourlyMoraleUpdate( void );
void DailyMoraleUpdate( SOLDIERTYPE *pSoldier );
void DecayTacticalMoraleModifiers( void );
#endif
+353
View File
@@ -0,0 +1,353 @@
#ifndef __OVERHEAD_TYPES_H
#define __OVERHEAD_TYPES_H
// GLOBAL HEADER FOR DATA, TYPES FOR TACTICAL ENGINE
#define REFINE_AIM_1 0
#define REFINE_AIM_MID1 1
#define REFINE_AIM_2 2
#define REFINE_AIM_MID2 3
#define REFINE_AIM_3 4
#define REFINE_AIM_MID3 5
#define REFINE_AIM_4 6
#define REFINE_AIM_MID4 7
#define REFINE_AIM_5 8
#define REFINE_AIM_BURST 10
#define AIM_SHOT_RANDOM 0
#define AIM_SHOT_HEAD 1
#define AIM_SHOT_TORSO 2
#define AIM_SHOT_LEGS 3
#define AIM_SHOT_GLAND 4
#define MIN_AMB_LEVEL_FOR_MERC_LIGHTS 9
#define MAXTEAMS 6
#define MAXMERCS MAX_NUM_SOLDIERS
//TACTICAL OVERHEAD STUFF
#define NO_SOLDIER TOTAL_SOLDIERS // SAME AS NOBODY
#define NOBODY NO_SOLDIER
// TACTICAL ENGINE STATUS FLAGS
#define REALTIME 0x000000002
#define TURNBASED 0x000000004
#define IN_ENDGAME_SEQUENCE 0x000000008
#define SHOW_ALL_ITEMS 0x000000010
#define SHOW_AP_LEFT 0x000000020
#define SHOW_ALL_MERCS 0x000000040
#define TRANSLUCENCY_TYPE 0x000000080
#define GODMODE 0x000000100
#define DEMOMODE 0x000000200
#define PLAYER_TEAM_DEAD 0x000000400
#define NPC_TEAM_DEAD 0x000000800
#define DISALLOW_SIGHT 0x000001000
#define CHECK_SIGHT_AT_END_OF_ATTACK 0x000002000
#define IN_CREATURE_LAIR 0x000004000
#define HIDE_TREES 0x000008000
#define NOHIDE_REDUNDENCY 0x000010000
#define DEBUGCLIFFS 0x000020000
#define INCOMBAT 0x000040000
#define ACTIVE 0x000100000
#define SHOW_Z_BUFFER 0x000200000
#define SLOW_ANIMATION 0x000400000
#define ENGAGED_IN_CONV 0x000800000
#define LOADING_SAVED_GAME 0x001000000
#define OUR_MERCS_AUTO_MOVE 0x002000000
#define SHOW_ALL_ROOFS 0x004000000
#define NEWLY_ENTERED_SECTOR 0x008000000
#define RED_ITEM_GLOW_ON 0x010000000
#define IGNORE_ENGAGED_IN_CONV_UI_UNLOCK 0x020000000
#define IGNORE_ALL_OBSTACLES 0x040000000
#define IN_DEIDRANNA_ENDGAME 0x080000000
#define DONE_DEIDRANNA_ENDGAME 0x100000000
#define OKBREATH 10
#define OKLIFE 15
#define CONSCIOUSNESS 10
// VIEWRANGE DEFINES
#define NORMAL_VIEW_RANGE 13
#define MIN_RANGE_FOR_BLOWNAWAY 40
// MODIFIERS FOR AP COST FOR MOVEMENT
#define RUNDIVISOR 1.8
#define WALKCOST -1
#define SWATCOST 0
#define CRAWLCOST 1
// defines
// ######################################################
#define MAX_PATH_LIST_SIZE 30
#define NUM_SOLDIER_SHADES 48
#define NUM_SOLDIER_EFFECTSHADES 2
// TIMER DELAYS
#define DAMAGE_DISPLAY_DELAY 250
#define FADE_DELAY 150
#define FLASH_SELECTOR_DELAY 4000
#define BLINK_SELECTOR_DELAY 250
#define PTR_OURTEAM (pSoldier->bTeam == gbPlayerNum)
#define DONTLOOK 0
#define LOOK 1
#define NOLOCATE 0
#define LOCATE 1
#define DONTSETLOCATOR 0
#define SETLOCATOR 1
#define SETANDREMOVEPREVIOUSLOCATOR 2
#define SETLOCATORFAST 3
#define NOCENTERING 0
#define NOUPDATE 0
#define UPDATE 1
// ORDERS
enum
{
STATIONARY = 0, // moves max 1 sq., no matter what's going on
ONGUARD, // moves max 2 sqs. until alerted by something
CLOSEPATROL, // patrols within 5 spaces until alerted
FARPATROL, // patrols within 15 spaces
POINTPATROL, // patrols using patrolGrids
ONCALL, // helps buddies anywhere within the sector
SEEKENEMY, // not tied down to any one particular spot
RNDPTPATROL, // patrols randomly using patrolGrids
//SNIPER, // snipes
MAXORDERS
};
// ATTITUDES
enum
{
DEFENSIVE = 0,
BRAVESOLO,
BRAVEAID,
CUNNINGSOLO,
CUNNINGAID,
AGGRESSIVE,
MAXATTITUDES,
ATTACKSLAYONLY // special hyperaggressive vs Slay only value for Carmen the bounty hunter
};
// alert status types
enum
{
STATUS_GREEN = 0, // everything's OK, no suspicion
STATUS_YELLOW, // he or his friend heard something
STATUS_RED, // has definite evidence of opponent
STATUS_BLACK, // currently sees an active opponent
NUM_STATUS_STATES
};
enum
{
MORALE_HOPELESS = 0,
MORALE_WORRIED,
MORALE_NORMAL,
MORALE_CONFIDENT,
MORALE_FEARLESS,
NUM_MORALE_STATES
};
// DEFINES FOR WEAPON HIT EVENT SPECIAL PARAM
#define FIRE_WEAPON_NO_SPECIAL 0
#define FIRE_WEAPON_BURST_SPECIAL 1
#define FIRE_WEAPON_HEAD_EXPLODE_SPECIAL 2
#define FIRE_WEAPON_CHEST_EXPLODE_SPECIAL 3
#define FIRE_WEAPON_LEG_FALLDOWN_SPECIAL 4
#define FIRE_WEAPON_HIT_BY_KNIFE_SPECIAL 5
#define FIRE_WEAPON_SLEEP_DART_SPECIAL 6
#define FIRE_WEAPON_BLINDED_BY_SPIT_SPECIAL 7
#define FIRE_WEAPON_TOSSED_OBJECT_SPECIAL 8
#define NO_INTERRUPTS 0
#define ALLOW_INTERRUPTS 1
#define SIGHT_LOOK 0x1
//#define SIGHT_SEND 0x2 // no longer needed using LOCAL OPPLISTs
#define SIGHT_RADIO 0x4
#define SIGHT_INTERRUPT 0x8
#define SIGHT_ALL 0xF
// CHANGE THIS VALUE TO AFFECT TOTAL SIGHT RANGE
#define STRAIGHT_RANGE 13
// CHANGE THESE VALUES TO ADJUST VARIOUS FOV ANGLES
#define STRAIGHT_RATIO 1 //* 1.5
#define ANGLE_RATIO 0.857 //* 1.5
#define SIDE_RATIO 0.571 //* 1.5
// CJC: Changed SBEHIND_RATIO (side-behind ratio) to be 0 to make stealth attacks easier
// Changed on September 21, 1998
//#define SBEHIND_RATIO 0.142
#define SBEHIND_RATIO 0
#define BEHIND_RATIO 0
// looking distance defines
#define BEHIND (INT8)( BEHIND_RATIO * STRAIGHT_RANGE )
#define SBEHIND (INT8)( SBEHIND_RATIO * STRAIGHT_RANGE )
#define SIDE (INT8)( SIDE_RATIO * STRAIGHT_RANGE )
#define ANGLE (INT8)( ANGLE_RATIO * STRAIGHT_RANGE )
#define STRAIGHT (INT8)( STRAIGHT_RATIO * STRAIGHT_RANGE )
// opplist value constants
#define HEARD_3_TURNS_AGO -4
#define HEARD_2_TURNS_AGO -3
#define HEARD_LAST_TURN -2
#define HEARD_THIS_TURN -1
#define NOT_HEARD_OR_SEEN 0
#define SEEN_CURRENTLY 1
#define SEEN_THIS_TURN 2
#define SEEN_LAST_TURN 3
#define SEEN_2_TURNS_AGO 4
#define SEEN_3_TURNS_AGO 5
#define OLDEST_SEEN_VALUE SEEN_3_TURNS_AGO
#define OLDEST_HEARD_VALUE HEARD_3_TURNS_AGO
#define UNDER_FIRE 2
#define UNDER_FIRE_LAST_TURN 1
#define MAX_DISTANCE_FOR_PROXIMITY_SIGHT 15
// DEFINES FOR BODY TYPE SUBSTITUTIONS
#define SUB_ANIM_BIGGUYSHOOT2 0x00000001
#define SUB_ANIM_BIGGUYTHREATENSTANCE 0x00000002
// Enumerate directions
enum WorldDirections
{
NORTH = 0,
NORTHEAST,
EAST,
SOUTHEAST,
SOUTH,
SOUTHWEST,
WEST,
NORTHWEST,
NUM_WORLD_DIRECTIONS,
DIRECTION_IRRELEVANT,
DIRECTION_EXITGRID = 255,
};
// ENUMERATION OF SOLDIER POSIITONS IN GLOBAL SOLDIER LIST
#define MAX_NUM_SOLDIERS 148
#define NUM_PLANNING_MERCS 8
#define TOTAL_SOLDIERS ( NUM_PLANNING_MERCS + MAX_NUM_SOLDIERS )
// DEFINE TEAMS
#define OUR_TEAM 0
#define ENEMY_TEAM 1
#define CREATURE_TEAM 2
#define MILITIA_TEAM 3
#define CIV_TEAM 4
#define LAST_TEAM CIV_TEAM
#define PLAYER_PLAN 5
//-----------------------------------------------
//
// civilian "sub teams":
enum
{
NON_CIV_GROUP = 0,
REBEL_CIV_GROUP,
KINGPIN_CIV_GROUP,
SANMONA_ARMS_GROUP,
ANGELS_GROUP,
BEGGARS_CIV_GROUP,
TOURISTS_CIV_GROUP,
ALMA_MILITARY_CIV_GROUP,
DOCTORS_CIV_GROUP,
COUPLE1_CIV_GROUP,
HICKS_CIV_GROUP,
WARDEN_CIV_GROUP,
JUNKYARD_CIV_GROUP,
FACTORY_KIDS_GROUP,
QUEENS_CIV_GROUP,
UNNAMED_CIV_GROUP_15,
UNNAMED_CIV_GROUP_16,
UNNAMED_CIV_GROUP_17,
UNNAMED_CIV_GROUP_18,
UNNAMED_CIV_GROUP_19,
NUM_CIV_GROUPS
};
#define CIV_GROUP_NEUTRAL 0
#define CIV_GROUP_WILL_EVENTUALLY_BECOME_HOSTILE 1
#define CIV_GROUP_WILL_BECOME_HOSTILE 2
#define CIV_GROUP_HOSTILE 3
// boxing state
enum BoxingStates
{
NOT_BOXING = 0,
BOXING_WAITING_FOR_PLAYER,
PRE_BOXING,
BOXING,
DISQUALIFIED,
WON_ROUND,
LOST_ROUND
} ;
//NOTE: The editor uses these enumerations, so please update the text as well if you modify or
// add new groups. Try to abbreviate the team name as much as possible. The text is in
// EditorMercs.c
#ifdef JA2EDITOR
extern UINT16 gszCivGroupNames[ NUM_CIV_GROUPS ][ 20 ];
#endif
//
//-----------------------------------------------
// PALETTE SUBSITUTION TYPES
typedef struct
{
UINT8 ubStart;
UINT8 ubEnd;
} PaletteSubRangeType;
typedef CHAR8 PaletteRepID[ 30 ];
typedef struct
{
UINT8 ubType;
PaletteRepID ID;
UINT8 ubPaletteSize;
UINT8 *r;
UINT8 *g;
UINT8 *b;
} PaletteReplacementType;
// MACROS
// This will set an animation ID
#define SET_PALETTEREP_ID( a, b ) ( strcpy( a, b ) )
// strcmp returns 0 if true!
#define COMPARE_PALETTEREP_ID( a, b ) ( strcmp( a, b ) ? FALSE : TRUE )
#endif
File diff suppressed because it is too large Load Diff
+373
View File
@@ -0,0 +1,373 @@
#ifndef __OVERHEAD_H
#define __OVERHEAD_H
#include <string.h>
#include <stdio.h>
//#include "container.h"
#include "Soldier Control.h"
#include "overhead types.h"
#include "soldier find.h"
#define ADD_SOLDIER_NO_PROFILE_ID 200
#define MAX_REALTIME_SPEED_VAL 10
/*
enum
{
TOPTION_SUBTITLES,
TOPTION_SPEECH,
TOPTION_KEY_ADVANCE_SPEECH,
TOPTION_RTCONFIRM,
TOPTION_HIDE_BULLETS,
TOPTION_TRACKING_MODE,
TOPTION_CONFIRM_MOVE,
TOPTION_MUTE_CONFIRMATIONS,
TOPTION_SHADOWS,
TOPTION_BLOOD_N_GORE,
NUM_TOPTIONS
};
*/
// Enums for waiting for mercs to finish codes
enum
{
NO_WAIT_EVENT = 0,
WAIT_FOR_MERCS_TO_WALKOFF_SCREEN,
WAIT_FOR_MERCS_TO_WALKON_SCREEN,
WAIT_FOR_MERCS_TO_WALK_TO_GRIDNO
};
// TACTICAL ENGINE STATUS FLAGS
typedef struct
{
UINT8 bFirstID;
UINT8 bLastID;
COLORVAL RadarColor;
INT8 bSide;
INT8 bMenInSector;
UINT8 ubLastMercToRadio;
INT8 bTeamActive;
INT8 bAwareOfOpposition;
INT8 bHuman;
} TacticalTeamType;
//for use with TacticalStatusType.ubEnemyIntention
enum
{
INTENTION_SCOUTING,
INTENTION_PATROLLING,
INTENTION_ATTACKING,
INTENTION_DEFENDING,
INTENTION_RETREATING
};
//for use with TacticalStatusType.ubEnemyIntendedRetreatDirection
enum
{
RETREAT_NORTH,
RETREAT_EAST,
RETREAT_SOUTH,
RETREAT_WEST
};
#define PANIC_BOMBS_HERE 0x01
#define PANIC_TRIGGERS_HERE 0x02
#define NUM_PANIC_TRIGGERS 3
#define ENEMY_OFFERED_SURRENDER 0x01
typedef struct
{
UINT32 uiFlags;
TacticalTeamType Team[ MAXTEAMS ];
UINT8 ubCurrentTeam;
INT16 sSlideTarget;
INT16 sSlideReason;
UINT32 uiTimeSinceMercAIStart;
INT8 fPanicFlags;
INT16 sPanicTriggerGridnoUnused;
INT16 sHandGrid;
UINT8 ubSpottersCalledForBy;
UINT8 ubTheChosenOne;
UINT32 uiTimeOfLastInput;
UINT32 uiTimeSinceDemoOn;
UINT32 uiCountdownToRestart;
BOOLEAN fGoingToEnterDemo;
BOOLEAN fNOTDOLASTDEMO;
BOOLEAN fMultiplayer;
BOOLEAN fCivGroupHostile[ NUM_CIV_GROUPS ];
UINT8 ubLastBattleSectorX;
UINT8 ubLastBattleSectorY;
BOOLEAN fLastBattleWon;
INT8 bOriginalSizeOfEnemyForce;
INT8 bPanicTriggerIsAlarmUnused;
BOOLEAN fVirginSector;
BOOLEAN fEnemyInSector;
BOOLEAN fInterruptOccurred;
INT8 bRealtimeSpeed;
UINT8 ubEnemyIntention;
UINT8 ubEnemyIntendedRetreatDirection;
UINT8 ubEnemySightingOnTheirTurnEnemyID;
UINT8 ubEnemySightingOnTheirTurnPlayerID;
BOOLEAN fEnemySightingOnTheirTurn;
BOOLEAN fAutoBandageMode;
UINT8 ubAttackBusyCount;
INT8 bNumEnemiesFoughtInBattleUnused;
UINT8 ubEngagedInConvFromActionMercID;
UINT16 usTactialTurnLimitCounter;
BOOLEAN fInTopMessage;
UINT8 ubTopMessageType;
INT16 zTopMessageString[20];
UINT16 usTactialTurnLimitMax;
UINT32 uiTactialTurnLimitClock;
BOOLEAN fTactialTurnLimitStartedBeep;
INT8 bBoxingState;
INT8 bConsNumTurnsNotSeen;
UINT8 ubArmyGuysKilled;
INT16 sPanicTriggerGridNo[ NUM_PANIC_TRIGGERS ];
INT8 bPanicTriggerIsAlarm[ NUM_PANIC_TRIGGERS ];
UINT8 ubPanicTolerance[ NUM_PANIC_TRIGGERS ];
BOOLEAN fAtLeastOneGuyOnMultiSelect;
BOOLEAN fSaidCreatureFlavourQuote;
BOOLEAN fHaveSeenCreature;
BOOLEAN fKilledEnemyOnAttack;
UINT8 ubEnemyKilledOnAttack;
INT8 bEnemyKilledOnAttackLevel;
UINT16 ubEnemyKilledOnAttackLocation;
BOOLEAN fItemsSeenOnAttack;
BOOLEAN ubItemsSeenOnAttackSoldier;
BOOLEAN fBeenInCombatOnce;
BOOLEAN fSaidCreatureSmellQuote;
UINT16 usItemsSeenOnAttackGridNo;
BOOLEAN fLockItemLocators;
UINT8 ubLastQuoteSaid;
UINT8 ubLastQuoteProfileNUm;
BOOLEAN fCantGetThrough;
INT16 sCantGetThroughGridNo;
INT16 sCantGetThroughSoldierGridNo;
UINT8 ubCantGetThroughID;
BOOLEAN fDidGameJustStart;
BOOLEAN fStatChangeCheatOn;
UINT8 ubLastRequesterTargetID;
BOOLEAN fGoodToAllowCrows;
UINT8 ubNumCrowsPossible;
UINT32 uiTimeCounterForGiveItemSrc;
BOOLEAN fUnLockUIAfterHiddenInterrupt;
INT8 bNumFoughtInBattle[ MAXTEAMS ];
UINT32 uiDecayBloodLastUpdate;
UINT32 uiTimeSinceLastInTactical;
BOOLEAN fHasAGameBeenStarted;
INT8 bConsNumTurnsWeHaventSeenButEnemyDoes;
BOOLEAN fSomeoneHit;
UINT8 ubPaddingSmall;
UINT32 uiTimeSinceLastOpplistDecay;
INT8 bMercArrivingQuoteBeingUsed;
UINT8 ubEnemyKilledOnAttackKiller;
BOOLEAN fCountingDownForGuideDescription;
INT8 bGuideDescriptionCountDown;
UINT8 ubGuideDescriptionToUse;
INT8 bGuideDescriptionSectorX;
INT8 bGuideDescriptionSectorY;
INT8 fEnemyFlags;
BOOLEAN fAutoBandagePending;
BOOLEAN fHasEnteredCombatModeSinceEntering;
BOOLEAN fDontAddNewCrows;
UINT8 ubMorePadding;
UINT16 sCreatureTenseQuoteDelay;
UINT32 uiCreatureTenseQuoteLastUpdate;
// PADDING GONE!!!!!
} TacticalStatusType;
extern UINT8 gbPlayerNum;
extern INT8 gbShowEnemies;
extern UINT16 gusSelectedSoldier;
extern UINT16 gusOldSelectedSoldier;
extern CHAR8 gzAlertStr[][ 30 ];
extern CHAR8 gzActionStr[][ 30 ];
extern CHAR8 gzDirectionStr[][ 30 ];
// TEMP FOR E3
extern UINT8 gubCurrentScene;
extern CHAR8 *GetSceneFilename( );
extern INT8 ubLevelMoveLink[ 10 ];
// Soldier List used for all soldier overhead interaction
extern SOLDIERTYPE Menptr[ TOTAL_SOLDIERS ];
extern SOLDIERTYPE *MercPtrs[ TOTAL_SOLDIERS ];
// MERC SLOTS - A LIST OF ALL ACTIVE MERCS
extern SOLDIERTYPE *MercSlots[ TOTAL_SOLDIERS ];
extern UINT32 guiNumMercSlots;
extern BOOLEAN gfMovingAnimation;
extern TacticalStatusType gTacticalStatus;
BOOLEAN InitTacticalEngine( );
void ShutdownTacticalEngine( );
BOOLEAN InitOverhead( );
BOOLEAN ShutdownOverhead( );
BOOLEAN GetSoldier( SOLDIERTYPE **ppSoldier, UINT16 usSoldierIndex );
INT16 NewOKDestination( SOLDIERTYPE * pCurrSoldier, INT16 sGridNo, BOOLEAN fPeopleToo, INT8 bLevel );
//Simple check to see if a (one-tiled) soldier can occupy a given location on the ground or roof.
extern BOOLEAN IsLocationSittable( INT32 iMapIndex, BOOLEAN fOnRoof );
extern BOOLEAN IsLocationSittableExcludingPeople( INT32 iMapIndex, BOOLEAN fOnRoof );
extern BOOLEAN FlatRoofAboveGridNo( INT32 iMapIndex );
BOOLEAN ExecuteOverhead( );
BOOLEAN ResetAllAnimationCache( );
void EndTurn( );
void EndTurn( UINT8 ubNextTeam );
void StartPlayerTeamTurn( BOOLEAN fDoBattleSnd, BOOLEAN fEnteringCombatMode );
void EndTacticalDemo( );
void SelectSoldier( UINT16 usSoldierID, BOOLEAN fAcknowledge, BOOLEAN fForceReselect );
//Kaiden: Function declaration from UB to reveal all items after combat.
void RevealAllDroppedEnemyItems();
void LocateGridNo( UINT16 sGridNo );
void LocateSoldier( UINT16 usID, BOOLEAN fSetLocator);
void BeginTeamTurn( UINT8 ubTeam );
void SlideTo(INT16 sGridno, UINT16 usSoldierID , UINT16 usReasonID, BOOLEAN fSetLocator) ;
void SlideToLocation( UINT16 usReasonID, INT16 sDestGridNo );
void RebuildAllSoldierShadeTables( );
void HandlePlayerTeamMemberDeath( SOLDIERTYPE *pSoldier );
UINT8 LastActiveTeamMember( UINT8 ubTeam );
BOOLEAN SoldierOnVisibleWorldTile( SOLDIERTYPE *pSoldier );
UINT8 FindNextActiveAndAliveMerc( SOLDIERTYPE *pSoldier, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs );
UINT8 FindPrevActiveAndAliveMerc( SOLDIERTYPE *pSoldier, BOOLEAN fGoodForLessOKLife, BOOLEAN fOnlyRegularMercs );
BOOLEAN CheckForPlayerTeamInMissionExit( );
void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldier );
void StopMercAnimation( BOOLEAN fStop );
UINT32 EnterTacticalDemoMode();
BOOLEAN UIOKMoveDestination( SOLDIERTYPE *pSoldier, UINT16 usMapPos );
INT16 FindAdjacentGridEx( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 *pubDirection, INT16 *psAdjustedGridNo, BOOLEAN fForceToPerson, BOOLEAN fDoor );
INT16 FindNextToAdjacentGridEx( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 *pubDirection, INT16 *psAdjustedGridNo, BOOLEAN fForceToPerson, BOOLEAN fDoor );
void SelectNextAvailSoldier( SOLDIERTYPE *pSoldier );
BOOLEAN TeamMemberNear(INT8 bTeam, INT16 sGridNo, INT32 iRange);
BOOLEAN IsValidTargetMerc( UINT8 ubSoldierID );
// FUNCTIONS FOR MANIPULATING MERC SLOTS - A LIST OF ALL ACTIVE MERCS
INT32 GetFreeMercSlot(void);
void RecountMercSlots(void);
INT32 AddMercSlot( SOLDIERTYPE *pSoldier );
BOOLEAN RemoveMercSlot( SOLDIERTYPE *pSoldier );
INT32 AddAwaySlot( SOLDIERTYPE *pSoldier );
BOOLEAN RemoveAwaySlot( SOLDIERTYPE *pSoldier );
INT32 MoveSoldierFromMercToAwaySlot( SOLDIERTYPE * pSoldier );
INT32 MoveSoldierFromAwayToMercSlot( SOLDIERTYPE * pSoldier );
void EnterCombatMode( UINT8 ubStartingTeam );
void ExitCombatMode( );
void HandleTeamServices( UINT8 ubTeamNum );
void HandlePlayerServices( SOLDIERTYPE *pTeamSoldier );
void SetEnemyPresence( );
void CycleThroughKnownEnemies( );
BOOLEAN CheckForEndOfCombatMode( BOOLEAN fIncrementTurnsNotSeen );
SOLDIERTYPE * FreeUpAttacker( UINT8 ubID );
BOOLEAN PlayerTeamFull( );
void SetActionToDoOnceMercsGetToLocation( UINT8 ubActionCode, INT8 bNumMercsWaiting, UINT32 uiData1, UINT32 uiData2, UINT32 uiData3 );
void ResetAllMercSpeeds( );
BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLEAN fInitialMove, UINT16 usAnimState );
SOLDIERTYPE * ReduceAttackBusyCount( UINT8 ubID, BOOLEAN fCalledByAttacker );
void CommonEnterCombatModeCode( );
void CheckForPotentialAddToBattleIncrement( SOLDIERTYPE *pSoldier );
void CencelAllActionsForTimeCompression( void );
BOOLEAN CheckForEndOfBattle( BOOLEAN fAnEnemyRetreated );
void AddManToTeam( INT8 bTeam );
void RemoveManFromTeam( INT8 bTeam );
void RemoveSoldierFromTacticalSector( SOLDIERTYPE *pSoldier, BOOLEAN fAdjustSelected );
void MakeCivHostile( SOLDIERTYPE *pSoldier, INT8 bNewSide );
#define REASON_NORMAL_ATTACK 1
#define REASON_EXPLOSION 2
BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** ppTarget, INT8 bReason );
INT16 FindAdjacentPunchTarget( SOLDIERTYPE * pSoldier, SOLDIERTYPE * pTargetSoldier, INT16 * psAdjustedTargetGridNo, UINT8 * pubDirection );
SOLDIERTYPE * CivilianGroupMemberChangesSides( SOLDIERTYPE * pAttacked );
void CivilianGroupChangesSides( UINT8 ubCivilianGroup );
void CycleVisibleEnemies( SOLDIERTYPE *pSrcSoldier );
UINT8 CivilianGroupMembersChangeSidesWithinProximity( SOLDIERTYPE * pAttacked );
void PauseAITemporarily( void );
void PauseAIUntilManuallyUnpaused( void );
void UnPauseAI( void );
void DoPOWPathChecks( void );
BOOLEAN HostileCiviliansWithGunsPresent( void );
BOOLEAN HostileCiviliansPresent( void );
BOOLEAN HostileBloodcatsPresent( void );
UINT8 NumPCsInSector( void );
void SetSoldierNonNeutral( SOLDIERTYPE * pSoldier );
void SetSoldierNeutral( SOLDIERTYPE * pSoldier );
extern BOOLEAN sniperwarning;
extern BOOLEAN biggunwarning;
extern BOOLEAN airstrikeavailable;
void CheckForAndSetupAirRaid ();
void EnemyCallInAirStrike (INT16 sSectorX, INT16 sSectorY);
// will a sam site under the players control shoot down an airraid?
BOOLEAN WillAirRaidBeStopped( INT16 sSectorX, INT16 sSectorY );
#endif
+123
View File
@@ -0,0 +1,123 @@
/*
Filename : pathai.h
Author : Ray E. Bornert II
Date : 1992-MAR-15
Copyright (C) 1993 HixoxiH Software
*/
#ifndef _PATHAI_H
#define _PATHAI_H
#include "isometric utils.h"
BOOLEAN InitPathAI( void );
void ShutDownPathAI( void );
INT16 PlotPath( SOLDIERTYPE *pSold, INT16 sDestGridno, INT8 bCopyRoute, INT8 bPlot, INT8 bStayOn, UINT16 usMovementMode, INT8 bStealth, INT8 bReverse , INT16 sAPBudget);
INT16 UIPlotPath( SOLDIERTYPE *pSold, INT16 sDestGridno, INT8 bCopyRoute, INT8 bPlot, INT8 bStayOn, UINT16 usMovementMode, INT8 bStealth, INT8 bReverse , INT16 sAPBudget);
INT16 EstimatePlotPath( SOLDIERTYPE *pSold, INT16 sDestGridno, INT8 bCopyRoute, INT8 bPlot, INT8 bStayOn, UINT16 usMovementMode, INT8 bStealth, INT8 bReverse , INT16 sAPBudget);
void ErasePath(char bEraseOldOne);
INT32 FindBestPath(SOLDIERTYPE *s , INT16 sDestination, INT8 ubLevel, INT16 usMovementMode, INT8 bCopy, UINT8 fFlags );
void GlobalReachableTest( INT16 sStartGridNo );
void GlobalItemsReachableTest( INT16 sStartGridNo1, INT16 sStartGridNo2 );
void RoofReachableTest( INT16 sStartGridNo, UINT8 ubBuildingID );
void LocalReachableTest( INT16 sStartGridNo, INT8 bRadius );
UINT8 DoorTravelCost( SOLDIERTYPE * pSoldier, INT32 iGridNo, UINT8 ubMovementCost, BOOLEAN fReturnPerceivedValue, INT32 * piDoorGridNo );
UINT8 InternalDoorTravelCost( SOLDIERTYPE * pSoldier, INT32 iGridNo, UINT8 ubMovementCost, BOOLEAN fReturnPerceivedValue, INT32 * piDoorGridNo, BOOLEAN fReturnDoorCost );
INT16 RecalculatePathCost( SOLDIERTYPE *pSoldier, UINT16 usMovementMode );
// Exporting these global variables
extern UINT32 guiPathingData[256];
extern UINT8 gubNPCAPBudget;
extern UINT16 gusNPCMovementMode;
extern UINT8 gubNPCDistLimit;
extern UINT8 gubNPCPathCount;
extern BOOLEAN gfPlotPathToExitGrid;
extern BOOLEAN gfNPCCircularDistLimit;
extern BOOLEAN gfEstimatePath;
extern BOOLEAN gfPathAroundObstacles;
extern UINT8 gubGlobalPathFlags;
// Ian's terrain values for travelling speed/pathing purposes
// Fixed by CJC March 4, 1998. Please do not change these unless familiar
// with how this will affect the path code!
#define TRAVELCOST_NONE 0
#define TRAVELCOST_FLAT 10
#define TRAVELCOST_BUMPY 12
#define TRAVELCOST_GRASS 12
#define TRAVELCOST_THICK 16
#define TRAVELCOST_DEBRIS 20
#define TRAVELCOST_SHORE 30
#define TRAVELCOST_KNEEDEEP 36
#define TRAVELCOST_DEEPWATER 50
#define TRAVELCOST_FENCE 40
// these values are used to indicate "this is an obstacle
// if there is a door (perceived) open/closed in this tile
#define TRAVELCOST_DOOR_CLOSED_HERE 220
#define TRAVELCOST_DOOR_CLOSED_N 221
#define TRAVELCOST_DOOR_CLOSED_W 222
#define TRAVELCOST_DOOR_OPEN_HERE 223
#define TRAVELCOST_DOOR_OPEN_N 224
#define TRAVELCOST_DOOR_OPEN_NE 225
#define TRAVELCOST_DOOR_OPEN_E 226
#define TRAVELCOST_DOOR_OPEN_SE 227
#define TRAVELCOST_DOOR_OPEN_S 228
#define TRAVELCOST_DOOR_OPEN_SW 229
#define TRAVELCOST_DOOR_OPEN_W 230
#define TRAVELCOST_DOOR_OPEN_NW 231
#define TRAVELCOST_DOOR_OPEN_N_N 232
#define TRAVELCOST_DOOR_OPEN_NW_N 233
#define TRAVELCOST_DOOR_OPEN_NE_N 234
#define TRAVELCOST_DOOR_OPEN_W_W 235
#define TRAVELCOST_DOOR_OPEN_SW_W 236
#define TRAVELCOST_DOOR_OPEN_NW_W 237
#define TRAVELCOST_NOT_STANDING 248
#define TRAVELCOST_OFF_MAP 249
#define TRAVELCOST_CAVEWALL 250
#define TRAVELCOST_HIDDENOBSTACLE 251
#define TRAVELCOST_DOOR 252
#define TRAVELCOST_OBSTACLE 253
#define TRAVELCOST_WALL 254
#define TRAVELCOST_EXITGRID 255
#define TRAVELCOST_TRAINTRACKS 30
#define TRAVELCOST_DIRTROAD 9
#define TRAVELCOST_PAVEDROAD 9
#define TRAVELCOST_FLATFLOOR 10
#define TRAVELCOST_BLOCKED (TRAVELCOST_OFF_MAP)
#define IS_TRAVELCOST_DOOR( x ) (x >= TRAVELCOST_DOOR_CLOSED_HERE && x <= TRAVELCOST_DOOR_OPEN_NW_W)
#define IS_TRAVELCOST_CLOSED_DOOR( x ) (x >= TRAVELCOST_DOOR_CLOSED_HERE && x << TRAVELCOST_DOOR_CLOSED_W)
// ------------------------------------------
// PLOT PATH defines
#define NOT_STEALTH 0
#define STEALTH 1
#define NO_PLOT 0
#define PLOT 1
#define TEMPORARY 0
#define PERMANENT 1
#define FORWARD 0
#define REVERSE 1
#define NO_COPYROUTE 0
#define COPYROUTE 1
#define COPYREACHABLE 2
#define COPYREACHABLE_AND_APS 3
#define PATH_THROUGH_PEOPLE 0x01
#define PATH_IGNORE_PERSON_AT_DEST 0x02
#define PATH_CLOSE_GOOD_ENOUGH 0x04
#define PATH_CLOSE_RADIUS 5
// ------------------------------------------
#endif
+2855
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
//#define PATHAI_VISIBLE_DEBUG
+2264
View File
File diff suppressed because it is too large Load Diff
+343
View File
@@ -0,0 +1,343 @@
#ifndef __POINTS_H_
#define __POINTS_H_
#define AP_MINIMUM 10 // no merc can have less for his turn
#define AP_MAXIMUM 25 // no merc can have more for his turn
#define AP_MONSTER_MAXIMUM 40 // no monster can have more for his turn
#define AP_VEHICLE_MAXIMUM 50 // no merc can have more for his turn
#define AP_INCREASE 10 // optional across-the-board AP boost
#define MAX_AP_CARRIED 5 // APs carried from turn-to-turn
// monster AP bonuses, expressed in 10ths (12 = 120% normal)
#define AP_YOUNG_MONST_FACTOR 15
#define AP_ADULT_MONST_FACTOR 12
#define AP_MONST_FRENZY_FACTOR 13
// AP penalty for a phobia situation (again, in 10ths)
#define AP_CLAUSTROPHOBE 9
#define AP_AFRAID_OF_INSECTS 8
#define AP_EXCHANGE_PLACES 5
// Action Point values
#define AP_REVERSE_MODIFIER 1
#define AP_STEALTH_MODIFIER 2
#define AP_STEAL_ITEM 10 // APs to steal item....
#define AP_TAKE_BLOOD 10
#define AP_TALK 6
#define AP_MOVEMENT_FLAT 3 // div by 2 for run, +2, for crawl, -1 for swat
#define AP_MOVEMENT_GRASS 4
#define AP_MOVEMENT_BUSH 5
#define AP_MOVEMENT_RUBBLE 6
#define AP_MOVEMENT_SHORE 7 // shallow wade
#define AP_MOVEMENT_LAKE 9 // deep wade -> slowest
#define AP_MOVEMENT_OCEAN 8 // swimming is faster than deep wade
#define AP_CHANGE_FACING 1 // turning to face any other direction
#define AP_CHANGE_TARGET 1 // aiming at a new target
#define AP_CATCH_ITEM 5 // turn to catch item
#define AP_TOSS_ITEM 8 // toss item from inv
#define AP_REFUEL_VEHICLE 10
/*
#define AP_MOVE_ITEM_FREE 0 // same place, pocket->pocket
#define AP_MOVE_ITEM_FAST 2 // hand, holster, ground only
#define AP_MOVE_ITEM_AVG 4 // everything else!
#define AP_MOVE_ITEM_SLOW 6 // vests, protective gear
*/
#define AP_MOVE_ITEM_FAST 4 // hand, holster, ground only
#define AP_MOVE_ITEM_SLOW 6 // vests, protective gear
#define AP_RADIO 5
#define AP_CROUCH 2
#define AP_PRONE 2
#define AP_LOOK_STANDING 1
#define AP_LOOK_CROUCHED 2
#define AP_LOOK_PRONE 2
#define AP_READY_KNIFE 0
#define AP_READY_PISTOL 1
#define AP_READY_RIFLE 2
#define AP_READY_SAW 0
// JA2Gold: reduced dual AP cost from 3 to 1
//#define AP_READY_DUAL 3
#define AP_READY_DUAL 1
#define AP_MIN_AIM_ATTACK 0 // minimum permitted extra aiming
#define AP_MAX_AIM_ATTACK 4 // maximum permitted extra aiming
#define AP_BURST 5
#define AP_DROP_BOMB 3
#define AP_RELOAD_GUN 5 // loading new clip/magazine
#define AP_START_FIRST_AID 5 // get the stuff out of medic kit
#define AP_PER_HP_FIRST_AID 1 // for each point healed
#define AP_STOP_FIRST_AID 3 // put everything away again
#define AP_START_REPAIR 5 // get the stuff out of repair kit
#define AP_GET_HIT 2 // struck by bullet, knife, explosion
#define AP_GET_WOUNDED_DIVISOR 4 // 1 AP lost for every 'divisor' dmg
#define AP_FALL_DOWN 4 // falling down (explosion, exhaustion)
#define AP_GET_THROWN 2 // get thrown back (by explosion)
#define AP_GET_UP 5 // getting up again
#define AP_ROLL_OVER 2 // flipping from back to stomach
#define AP_OPEN_DOOR 3 // whether successful, or not (locked)
#define AP_PICKLOCK 10 // should really be several turns
#define AP_EXAMINE_DOOR 5 // time to examine door
#define AP_BOOT_DOOR 8 // time to boot door
#define AP_USE_CROWBAR 10 // time to crowbar door
#define AP_UNLOCK_DOOR 6 // time to unlock door
#define AP_LOCK_DOOR 6 // time to lock door
#define AP_EXPLODE_DOOR 10 // time to set explode charge on door
#define AP_UNTRAP_DOOR 10 // time to untrap door
#define AP_USEWIRECUTTERS 10 // Time to use wirecutters
#define AP_CLIMBROOF 10 // APs to climb roof
#define AP_CLIMBOFFROOF 6 // APs to climb off roof
#define AP_JUMPFENCE 6 // time to jump over a fence
#define AP_OPEN_SAFE 8 // time to use combination
#define AP_USE_REMOTE 2
#define AP_PULL_TRIGGER 2 // operate nearby panic trigger
#define AP_FORCE_LID_OPEN 10
#define AP_SEARCH_CONTAINER 5 // boxes, crates, safe, etc.
#define AP_READ_NOTE 10 // reading a note's contents in inv.
#define AP_SNAKE_BATTLE 10 // when first attacked
#define AP_KILL_SNAKE 7 // when snake battle's been won
#define AP_USE_SURV_CAM 5
#define AP_PICKUP_ITEM 3
#define AP_GIVE_ITEM 1
#define AP_BURY_MINE 10
#define AP_DISARM_MINE 10
#define AP_DRINK 5
#define AP_CAMOFLAGE 10
#define AP_TAKE_PHOTOGRAPH 5
#define AP_MERGE 8
#define AP_OTHER_COST 99
#define AP_START_RUN_COST 1
#define AP_ATTACH_CAN 5
#define AP_JUMP_OVER 6
// special Breath Point related constants
#define BP_RATIO_RED_PTS_TO_NORMAL 100
#define BP_RUN_ENERGYCOSTFACTOR 3 // Richard thinks running is 3rd most strenous over time... tough, Mark didn't. CJC increased it again
#define BP_WALK_ENERGYCOSTFACTOR 1 // walking subtracts flat terrain breath value
#define BP_SWAT_ENERGYCOSTFACTOR 2 // Richard thinks swatmove is 2nd most strenous over time... tough, Mark didn't
#define BP_CRAWL_ENERGYCOSTFACTOR 4 // Richard thinks crawling is the MOST strenuous over time
#define BP_RADIO 0 // no breath cost
#define BP_USE_DETONATOR 0 // no breath cost
#define BP_REVERSE_MODIFIER 0 // no change, a bit more challenging
#define BP_STEALTH_MODIFIER -20 // slow & cautious, not too strenuous
#define BP_MINING_MODIFIER -30 // pretty relaxing, overall
// end-of-turn Breath Point gain/usage rates
#define BP_PER_AP_NO_EFFORT -200 // gain breath!
#define BP_PER_AP_MIN_EFFORT -100 // gain breath!
#define BP_PER_AP_LT_EFFORT -50 // gain breath!
#define BP_PER_AP_MOD_EFFORT 25
#define BP_PER_AP_HVY_EFFORT 50
#define BP_PER_AP_MAX_EFFORT 100
// Breath Point values
#define BP_MOVEMENT_FLAT 5
#define BP_MOVEMENT_GRASS 10
#define BP_MOVEMENT_BUSH 20
#define BP_MOVEMENT_RUBBLE 35
#define BP_MOVEMENT_SHORE 50 // shallow wade
#define BP_MOVEMENT_LAKE 75 // deep wade
#define BP_MOVEMENT_OCEAN 100 // swimming
#define BP_CHANGE_FACING 10 // turning to face another direction
#define BP_CROUCH 10
#define BP_PRONE 10
#define BP_CLIMBROOF 500 // BPs to climb roof
#define BP_CLIMBOFFROOF 250 // BPs to climb off roof
#define BP_JUMPFENCE 200 // BPs to jump fence
/*
#define BP_MOVE_ITEM_FREE 0 // same place, pocket->pocket
#define BP_MOVE_ITEM_FAST 0 // hand, holster, ground only
#define BP_MOVE_ITEM_AVG 0 // everything else!
#define BP_MOVE_ITEM_SLOW 20 // vests, protective gear
*/
#define BP_MOVE_ITEM_FAST 0 // hand, holster, ground only
#define BP_MOVE_ITEM_SLOW 20 // vests, protective gear
#define BP_READY_KNIFE 0 // raise/lower knife
#define BP_READY_PISTOL 10 // raise/lower pistol
#define BP_READY_RIFLE 20 // raise/lower rifle
#define BP_READY_SAW 0 // raise/lower saw
#define BP_STEAL_ITEM 50 // BPs steal item
#define BP_PER_AP_AIMING 5 // breath cost while aiming
#define BP_RELOAD_GUN 20 // loading new clip/magazine
#define BP_THROW_ITEM 50 // throw grenades, fire-bombs, etc.
#define BP_START_FIRST_AID 0 // get the stuff out of medic kit
#define BP_PER_HP_FIRST_AID -25 // gain breath for each point healed
#define BP_STOP_FIRST_AID 0 // put everything away again
#define BP_GET_HIT 200 // struck by bullet, knife, explosion
#define BP_GET_WOUNDED 50 // per pt of GUNFIRE/EXPLOSION impact
#define BP_FALL_DOWN 250 // falling down (explosion, exhaustion)
#define BP_GET_UP 50 // getting up again
#define BP_ROLL_OVER 20 // flipping from back to stomach
#define BP_OPEN_DOOR 30 // whether successful, or not (locked)
#define BP_PICKLOCK -250 // gain breath, not very tiring...
#define BP_EXAMINE_DOOR -250 // gain breath, not very tiring...
#define BP_BOOT_DOOR 200 // BP to boot door
#define BP_USE_CROWBAR 350 // BP to crowbar door
#define BP_UNLOCK_DOOR 50 // BP to unlock door
#define BP_EXPLODE_DOOR -250 // BP to set explode charge on door
#define BP_UNTRAP_DOOR 150 // BP to untrap
#define BP_LOCK_DOOR 50 // BP to untrap
#define BP_USEWIRECUTTERS 200 // BP to use wirecutters
#define BP_PULL_TRIGGER 0 // for operating panic triggers
#define BP_FORCE_LID_OPEN 50 // per point of strength required
#define BP_SEARCH_CONTAINER 0 // get some breath back (was -50)
#define BP_OPEN_SAFE -50
#define BP_READ_NOTE -250 // reading a note's contents in inv.
#define BP_SNAKE_BATTLE 500 // when first attacked
#define BP_KILL_SNAKE 350 // when snake battle's been won
#define BP_USE_SURV_CAM -100
#define BP_BURY_MINE 250 // involves digging & filling again
#define BP_DISARM_MINE 0 // 1/2 digging, 1/2 light effort
#define BP_FIRE_HANDGUN 25 // preatty easy, little recoil
#define BP_FIRE_RIFLE 50 // heavier, nasty recoil
#define BP_FIRE_SHOTGUN 100 // quite tiring, must be pumped up
#define BP_STAB_KNIFE 200
#define BP_TAKE_PHOTOGRAPH 0
#define BP_MERGE 50
#define BP_FALLFROMROOF 1000
#define BP_JUMP_OVER 250
#define DEFAULT_APS 20
#define DEFAULT_AIMSKILL 80
UINT8 BaseAPsToShootOrStab( INT8 bAPs, INT8 bAimSkill, OBJECTTYPE * pObj );
INT16 TerrainActionPoints( SOLDIERTYPE *pSoldier, INT16 sGridno, INT8 bDir, INT8 bLevel );
INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 usMovementMode );
INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bDir, UINT16 usMovementMode, INT8 bPathIndex, INT8 bPathLength );
BOOLEAN SelectedMercCanAffordMove( );
BOOLEAN EnoughPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost, BOOLEAN fDisplayMsg );
void DeductPoints( SOLDIERTYPE *pSoldier, INT16 sAPCost, INT32 iBPCost, BOOLEAN fProactive = TRUE );
INT32 AdjustBreathPts(SOLDIERTYPE *pSold, INT32 iBPCost);
void UnusedAPsToBreath(SOLDIERTYPE *pSold);
INT16 TerrainBreathPoints(SOLDIERTYPE * pSoldier, INT16 sGridno,INT8 bDir, UINT16 usMovementMode);
UINT8 MinAPsToAttack(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubAddTurningCost);
INT8 MinPtsToMove(SOLDIERTYPE *pSoldier);
INT8 MinAPsToStartMovement( SOLDIERTYPE * pSoldier, UINT16 usMovementMode );
INT8 PtsToMoveDirection(SOLDIERTYPE *pSoldier, INT8 bDirection );
UINT8 MinAPsToShootOrStab(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubAddTurningCost );
BOOLEAN EnoughAmmo( SOLDIERTYPE *pSoldier, BOOLEAN fDisplay, INT8 bInvPos );
void DeductAmmo( SOLDIERTYPE *pSoldier, INT8 bInvPos );
UINT16 GetAPsToPickupItem( SOLDIERTYPE *pSoldier, UINT16 usMapPos );
UINT8 MinAPsToPunch(SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubAddTurningCost );
UINT8 CalcTotalAPsToAttack( SOLDIERTYPE *pSoldier, INT16 sGridno, UINT8 ubAddTurningCost, INT8 bAimTime );
UINT8 CalcAPsToBurst( INT8 bBaseActionPoints, OBJECTTYPE * pObj );
UINT8 CalcAPsToAutofire( INT8 bBaseActionPoints, OBJECTTYPE * pObj, UINT8 bDoAutofire );
UINT16 GetAPsToChangeStance( SOLDIERTYPE *pSoldier, INT8 bDesiredHeight );
UINT16 GetBPsToChangeStance( SOLDIERTYPE *pSoldier, INT8 bDesiredHeight );
UINT16 GetAPsToLook( SOLDIERTYPE *pSoldier );
UINT16 GetAPsToGiveItem( SOLDIERTYPE *pSoldier, UINT16 usMapPos );
BOOLEAN CheckForMercContMove( SOLDIERTYPE *pSoldier );
INT16 GetAPsToReadyWeapon( SOLDIERTYPE *pSoldier, UINT16 usAnimState );
INT8 GetAPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown );
INT16 GetBPsToClimbRoof( SOLDIERTYPE *pSoldier, BOOLEAN fClimbDown );
INT8 GetAPsToJumpFence( SOLDIERTYPE *pSoldier );
INT8 GetBPsToJumpFence( SOLDIERTYPE *pSoldier );
INT8 GetAPsToCutFence( SOLDIERTYPE *pSoldier );
INT8 GetAPsToBeginFirstAid( SOLDIERTYPE *pSoldier );
INT8 GetAPsToBeginRepair( SOLDIERTYPE *pSoldier );
INT8 GetAPsToRefuelVehicle( SOLDIERTYPE *pSoldier );
INT16 MinAPsToThrow( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost );
UINT16 GetAPsToDropBomb( SOLDIERTYPE *pSoldier );
UINT16 GetTotalAPsToDropBomb( SOLDIERTYPE *pSoldier, INT16 sGridNo );
UINT16 GetAPsToUseRemote( SOLDIERTYPE *pSoldier );
INT8 GetAPsToStealItem( SOLDIERTYPE *pSoldier, INT16 usMapPos );
INT8 GetBPsToStealItem( SOLDIERTYPE *pSoldier );
INT8 GetAPsToUseJar( SOLDIERTYPE *pSoldier, INT16 usMapPos );
INT8 GetAPsToUseCan( SOLDIERTYPE *pSoldier, INT16 usMapPos );
INT8 GetBPsTouseJar( SOLDIERTYPE *pSoldier );
INT8 GetAPsToJumpOver( SOLDIERTYPE *pSoldier );
void GetAPChargeForShootOrStabWRTGunRaises( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubAddTurningCost, BOOLEAN *pfChargeTurning, BOOLEAN *pfChargeRaise );
UINT16 GetAPsToReloadRobot( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pRobot );
INT8 GetAPsToReloadGunWithAmmo( OBJECTTYPE * pGun, OBJECTTYPE * pAmmo );
INT8 GetAPsToAutoReload( SOLDIERTYPE * pSoldier );
#endif
+1259
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+188
View File
@@ -0,0 +1,188 @@
#ifndef _ROTTING_CORPSES_H
#define _ROTTING_CORPSES_H
#include "tile animation.h"
#define NUM_CORPSE_SHADES 17
enum RottingCorpseDefines
{
NO_CORPSE,
SMERC_JFK,
SMERC_BCK,
SMERC_FWD,
SMERC_DHD,
SMERC_PRN,
SMERC_WTR,
SMERC_FALL,
SMERC_FALLF,
MMERC_JFK,
MMERC_BCK,
MMERC_FWD,
MMERC_DHD,
MMERC_PRN,
MMERC_WTR,
MMERC_FALL,
MMERC_FALLF,
FMERC_JFK,
FMERC_BCK,
FMERC_FWD,
FMERC_DHD,
FMERC_PRN,
FMERC_WTR,
FMERC_FALL,
FMERC_FALLF,
// CIVS
M_DEAD1,
K_DEAD1,
H_DEAD1,
FT_DEAD1,
S_DEAD1,
W_DEAD1,
C_DEAD1,
M_DEAD2,
K_DEAD2,
H_DEAD2,
FT_DEAD2,
S_DEAD2,
W_DEAD2,
C_DEAD2,
BLOODCAT_DEAD,
COW_DEAD,
ADULTMONSTER_DEAD,
INFANTMONSTER_DEAD,
LARVAEMONSTER_DEAD,
ROTTING_STAGE2,
TANK1_DEAD,
TANK2_DEAD,
HUMMER_DEAD,
ICECREAM_DEAD,
QUEEN_MONSTER_DEAD,
ROBOT_DEAD,
BURNT_DEAD,
EXPLODE_DEAD,
NUM_CORPSES,
} ;
#define ROTTING_CORPSE_FIND_SWEETSPOT_FROM_GRIDNO 0x01 //Find the closest spot to the given gridno
#define ROTTING_CORPSE_USE_NORTH_ENTRY_POINT 0x02 //Find the spot closest to the north entry grid
#define ROTTING_CORPSE_USE_SOUTH_ENTRY_POINT 0x04 //Find the spot closest to the south entry grid
#define ROTTING_CORPSE_USE_EAST_ENTRY_POINT 0x08 //Find the spot closest to the east entry grid
#define ROTTING_CORPSE_USE_WEST_ENTRY_POINT 0x10 //Find the spot closest to the west entry grid
#define ROTTING_CORPSE_USE_CAMMO_PALETTE 0x20 //We use cammo palette here....
#define ROTTING_CORPSE_VEHICLE 0x40 //Vehicle Corpse
typedef struct
{
UINT8 ubType;
UINT8 ubBodyType;
INT16 sGridNo;
FLOAT dXPos;
FLOAT dYPos;
INT16 sHeightAdjustment;
PaletteRepID HeadPal; // Palette reps
PaletteRepID PantsPal;
PaletteRepID VestPal;
PaletteRepID SkinPal;
INT8 bDirection;
UINT32 uiTimeOfDeath;
UINT16 usFlags;
INT8 bLevel;
INT8 bVisible;
INT8 bNumServicingCrows;
UINT8 ubProfile;
BOOLEAN fHeadTaken;
UINT8 ubAIWarningValue;
UINT8 ubFiller[ 12 ];
} ROTTING_CORPSE_DEFINITION;
typedef struct
{
ROTTING_CORPSE_DEFINITION def;
BOOLEAN fActivated;
ANITILE *pAniTile;
SGPPaletteEntry *p8BPPPalette;
UINT16 *p16BPPPalette;
UINT16 *pShades[ NUM_CORPSE_SHADES ];
INT16 sGraphicNum;
INT32 iCachedTileID;
FLOAT dXPos;
FLOAT dYPos;
BOOLEAN fAttractCrowsOnlyWhenOnScreen;
INT32 iID;
} ROTTING_CORPSE;
INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef );
void RemoveCorpse( INT32 iCorpseID );
void RemoveCorpses( );
BOOLEAN TurnSoldierIntoCorpse( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveMerc, BOOLEAN fCheckForLOS );
INT16 FindNearestRottingCorpse( SOLDIERTYPE *pSoldier );
void AllMercsOnTeamLookForCorpse( ROTTING_CORPSE *pCorpse, INT8 bTeam );
void MercLooksForCorpses( SOLDIERTYPE *pSoldier );
void RebuildAllCorpseShadeTables( );
UINT16 CreateCorpsePaletteTables( ROTTING_CORPSE *pCorpse );
INT16 FindNearestAvailableGridNoForCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef, INT8 ubRadius );
void HandleRottingCorpses( );
void AddCrowToCorpse( ROTTING_CORPSE *pCorpse );
void VaporizeCorpse( INT16 sGridNo, UINT16 usStructureID );
void CorpseHit( INT16 sGridNo, UINT16 usStructureID );
void HandleCrowLeave( SOLDIERTYPE *pSoldier );
void HandleCrowFlyAway( SOLDIERTYPE *pSoldier );
#define MAX_ROTTING_CORPSES 100
extern ROTTING_CORPSE gRottingCorpse[ MAX_ROTTING_CORPSES ];
extern INT32 giNumRottingCorpse;
extern UINT8 gb4DirectionsFrom8[8];
ROTTING_CORPSE *GetCorpseAtGridNo( INT16 sGridNo , INT8 bLevel );
BOOLEAN IsValidDecapitationCorpse( ROTTING_CORPSE *pCorpse );
void DecapitateCorpse( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel );
void GetBloodFromCorpse( SOLDIERTYPE *pSoldier );
UINT16 GetCorpseStructIndex( ROTTING_CORPSE_DEFINITION *pCorpseDef, BOOLEAN fForImage );
void LookForAndMayCommentOnSeeingCorpse( SOLDIERTYPE *pSoldier, INT16 sGridNo, UINT8 ubLevel );
INT16 GetGridNoOfCorpseGivenProfileID( UINT8 ubProfileID );
void DecayRottingCorpseAIWarnings( void );
UINT8 GetNearestRottingCorpseAIWarning( INT16 sGridNo );
#endif
File diff suppressed because it is too large Load Diff
+124
View File
@@ -0,0 +1,124 @@
#ifndef _SHOPKEEPER_INTERFACE__H_
#define _SHOPKEEPER_INTERFACE__H_
#include "Store Inventory.h"
#define SKI_NUM_TRADING_INV_SLOTS 12
#define SKI_NUM_TRADING_INV_ROWS 2
#define SKI_NUM_TRADING_INV_COLS 6
//Enums used for when the user clicks on an item and the item goes to..
enum
{
ARMS_DEALER_INVENTORY,
ARMS_DEALER_OFFER_AREA,
PLAYERS_OFFER_AREA,
PLAYERS_INVENTORY,
};
#define ARMS_INV_ITEM_SELECTED 0x00000001 // The item has been placed into the offer area
//#define ARMS_INV_PLAYERS_ITEM_SELECTED 0x00000002 // The source location for the item has been selected
#define ARMS_INV_PLAYERS_ITEM_HAS_VALUE 0x00000004 // The Players item is worth something to this dealer
//#define ARMS_INV_ITEM_HIGHLIGHTED 0x00000008 // If the items is highlighted
#define ARMS_INV_ITEM_NOT_REPAIRED_YET 0x00000010 // The item is in for repairs but not repaired yet
#define ARMS_INV_ITEM_REPAIRED 0x00000020 // The item is repaired
#define ARMS_INV_JUST_PURCHASED 0x00000040 // The item was just purchased
#define ARMS_INV_PLAYERS_ITEM_HAS_BEEN_EVALUATED 0x00000080 // The Players item has been evaluated
typedef struct
{
BOOLEAN fActive;
INT16 sItemIndex;
UINT32 uiFlags;
OBJECTTYPE ItemObject;
UINT8 ubLocationOfObject; //An enum value for the location of the item ( either in the arms dealers inventory, one of the offer areas or in the users inventory)
INT8 bSlotIdInOtherLocation;
UINT8 ubIdOfMercWhoOwnsTheItem;
UINT32 uiItemPrice; //Only used for the players item that have been evaluated
INT16 sSpecialItemElement; // refers to which special item element an item in a dealer's inventory area
// occupies. -1 Means the item is "perfect" and has no associated special item.
} INVENTORY_IN_SLOT;
extern INVENTORY_IN_SLOT PlayersOfferArea[ SKI_NUM_TRADING_INV_SLOTS ];
extern INT32 giShopKeepDialogueEventinProgress;
//extern BOOLEAN gfRedrawSkiScreen;
enum
{
SKI_DIRTY_LEVEL0, // no redraw
SKI_DIRTY_LEVEL1, // redraw only items
SKI_DIRTY_LEVEL2, // redraw everything
};
extern UINT8 gubSkiDirtyLevel;
extern OBJECTTYPE *gpHighLightedItemObject;
extern INVENTORY_IN_SLOT gMoveingItem;
extern OBJECTTYPE *pShopKeeperItemDescObject;
UINT32 ShopKeeperScreenInit( void );
UINT32 ShopKeeperScreenHandle( void );
UINT32 ShopKeeperScreenShutdown( void );
void EnterShopKeeperInterfaceScreen( UINT8 ubArmsDealer );
void DrawHatchOnInventory( UINT32 uiSurface, UINT16 usPosX, UINT16 usPosY, UINT16 usWidth, UINT16 usHeight );
BOOLEAN ShouldSoldierDisplayHatchOnItem( UINT8 ubProfileID, INT16 sSlotNum );
INT8 AddItemToPlayersOfferArea( UINT8 ubProfileID, INVENTORY_IN_SLOT* pInvSlot, INT8 bSlotIdInOtherLocation );
void ConfirmToDeductMoneyFromPlayersAccountMessageBoxCallBack( UINT8 bExitValue );
void ConfirmDontHaveEnoughForTheDealerMessageBoxCallBack( UINT8 bExitValue );
void SkiHelpTextDoneCallBack( void );
void SetSkiCursor( UINT16 usCursor );
void InitShopKeeperSubTitledText( STR16 pString );
void AddItemToPlayersOfferAreaAfterShopKeeperOpen( OBJECTTYPE *pItemObject, INT8 bPreviousInvPos );
void BeginSkiItemPointer( UINT8 ubSource, INT8 bSlotNum, BOOLEAN fOfferToDealerFirst );
void DeleteShopKeeperItemDescBox();
BOOLEAN CanMercInteractWithSelectedShopkeeper( SOLDIERTYPE *pSoldier );
void DealerGetsBribed( UINT8 ubProfileId, UINT32 uiMoneyAmount );
#ifdef JA2TESTVERSION
void AddShopkeeperToGridNo( UINT8 ubProfile, INT16 sGridNo );
#endif
void RestrictSkiMouseCursor();
#endif
+49
View File
@@ -0,0 +1,49 @@
#ifndef _SHOPKEEPER_QUOTES_H_
#define _SHOPKEEPER_QUOTES_H_
// COMMON shop keeper quote enums
enum
{
// Quotes 0-9 are generic NPC quotes common to everyone and controlled by the normal NPC Dialogue system.
//10
SK_QUOTES_DEALER_OFFERED_MONEY_AS_A_GIFT = 10,
SK_QUOTES_PLAYER_FIRST_ENTERS_SKI,
SK_QUOTES_RANDOM_QUOTE_WHILE_PLAYER_DECIDING_1,
SK_QUOTES_RANDOM_QUOTE_WHILE_PLAYER_DECIDING_2,
SK_QUOTES_RANDOM_QUOTE_WHILE_ITEMS_CHOSEN_TO_TRADE,
//15
SK_QUOTES_RANDOM_QUOTE_WHILE_ITEMS_CHOSEN_TO_SELL_OR_REPAIR,
SK_QUOTES_PLAYER_REQUESTED_EVALUATION,
SK_QUOTES_DURING_EVALUATION_STUFF_REJECTED,
SK_QUOTES_EVALUATION_RESULT_VALUE_OF_ZERO,
SK_QUOTES_EVALUATION_RESULT_SOME_REALLY_DAMAGED_ITEMS,
//20
SK_QUOTES_EVALUATION_RESULT_NORMAL,
SK_QUOTES_EVAULATION_PLAYER_DOESNT_HAVE_ENOUGH_VALUE,
SK_QUOTES_PLAYER_HAS_EXACTLY_ENOUGH_MONEY_FOR_TRANSACTION,
SK_QUOTES_PLAYER_HAS_TOO_MUCH_MONEY_FOR_TRANSACTION,
SK_QUOTES_PRESSES_DONE_HAS_AT_LEAST_1_TRANSACTION,
//25
SK_QUOTES_PRESSED_DONE_HASNT_MADE_TRANSACTION,
SK_QUOTES_PRESSED_DONE_STILL_HAS_STUFF_IN_OFFER_AREA,
SK_QUOTES_CANT_AFFORD_TO_BUY_OR_TOO_MUCH_TO_REPAIR,
NUM_COMMON_SK_QUOTES,
// Quotes 28+ are NPC Specific, and are not under direct control of the SKI system. The get used by .COD files
};
// Common quotes needed by SKI
#define SK_QUOTES_NOT_INTERESTED_IN_THIS_ITEM 4
// NPC SPECIFIC shopkeeper_quotes
#define FREDO_QUOTE_CAN_RESET_IMPRINTING 31
#define FREDO_PERKO_SORRY_REPAIR_DELAYED 29
#define ARNIE_QUOTE_NOT_REPAIRED_YET 33
#endif
+525
View File
@@ -0,0 +1,525 @@
#ifdef PRECOMPILEDHEADERS
#include "Tactical All.h"
#else
#include "SkillCheck.h"
#include "Soldier Profile.h"
#include "Random.h"
#include "Items.h"
#include "Dialogue Control.h"
#include "Overhead.h"
#include "Soldier macros.h"
#include "Isometric Utils.h"
#include "Morale.h"
#include "drugs and alcohol.h"
#include "strategicmap.h"
#endif
INT8 EffectiveStrength( SOLDIERTYPE * pSoldier )
{
INT8 bBandaged;
INT32 iEffStrength;
// Effective strength is:
// 1/2 full strength
// plus 1/2 strength scaled according to how hurt we are
bBandaged = pSoldier->bLifeMax - pSoldier->bLife - pSoldier->bBleeding;
iEffStrength = pSoldier->bStrength / 2;
iEffStrength += (pSoldier->bStrength / 2) * (pSoldier->bLife + bBandaged / 2) / (pSoldier->bLifeMax);
// ATE: Make sure at least 2...
iEffStrength = __max( iEffStrength, 2 );
return( (INT8) iEffStrength );
}
INT8 EffectiveWisdom( SOLDIERTYPE * pSoldier )
{
INT32 iEffWisdom;
iEffWisdom = pSoldier->bWisdom;
iEffWisdom = EffectStatForBeingDrunk( pSoldier, iEffWisdom );
return( (INT8) iEffWisdom );
}
INT8 EffectiveAgility( SOLDIERTYPE * pSoldier )
{
INT32 iEffAgility;
iEffAgility = pSoldier->bAgility;
iEffAgility = EffectStatForBeingDrunk( pSoldier, iEffAgility );
if ( pSoldier->sWeightCarriedAtTurnStart > 100 )
{
iEffAgility = (iEffAgility * 100) / pSoldier->sWeightCarriedAtTurnStart;
}
return( (INT8) iEffAgility );
}
INT8 EffectiveMechanical( SOLDIERTYPE * pSoldier )
{
INT32 iEffMechanical;
iEffMechanical = pSoldier->bMechanical;
iEffMechanical = EffectStatForBeingDrunk( pSoldier, iEffMechanical );
return( (INT8) iEffMechanical );
}
INT8 EffectiveExplosive( SOLDIERTYPE * pSoldier )
{
INT32 iEffExplosive;
iEffExplosive = pSoldier->bExplosive;
iEffExplosive = EffectStatForBeingDrunk( pSoldier, iEffExplosive );
return( (INT8) iEffExplosive );
}
INT8 EffectiveMedical( SOLDIERTYPE * pSoldier )
{
INT32 iEffMedical;
iEffMedical = pSoldier->bMedical;
iEffMedical = EffectStatForBeingDrunk( pSoldier, iEffMedical );
return( (INT8) iEffMedical );
}
INT8 EffectiveLeadership( SOLDIERTYPE * pSoldier )
{
INT32 iEffLeadership;
INT8 bDrunkLevel;
iEffLeadership = pSoldier->bLeadership;
// if we are drunk, effect leader ship in a +ve way...
bDrunkLevel = GetDrunkLevel( pSoldier );
if ( bDrunkLevel == FEELING_GOOD )
{
iEffLeadership = ( iEffLeadership * 120 / 100 );
}
return( (INT8) iEffLeadership );
}
INT8 EffectiveExpLevel( SOLDIERTYPE * pSoldier )
{
INT32 iEffExpLevel;
INT8 bDrunkLevel;
INT32 iExpModifier[] =
{ 0, // SOBER
0, // Feeling good
-1, // Borderline
-2, // Drunk
0, // Hung
};
iEffExpLevel = pSoldier->bExpLevel;
bDrunkLevel = GetDrunkLevel( pSoldier );
iEffExpLevel = iEffExpLevel + iExpModifier[ bDrunkLevel ];
if (pSoldier->ubProfile != NO_PROFILE)
{
if ( (gMercProfiles[ pSoldier->ubProfile ].bPersonalityTrait == CLAUSTROPHOBIC) && pSoldier->bActive && pSoldier->bInSector && gbWorldSectorZ > 0)
{
// claustrophobic!
iEffExpLevel--;
}
}
if (iEffExpLevel < 1)
{
// can't go below 1
return( 1 );
}
else
{
return( (INT8) iEffExpLevel );
}
}
INT8 EffectiveMarksmanship( SOLDIERTYPE * pSoldier )
{
INT32 iEffMarksmanship;
iEffMarksmanship = pSoldier->bMarksmanship;
iEffMarksmanship = EffectStatForBeingDrunk( pSoldier, iEffMarksmanship );
return( (INT8) iEffMarksmanship );
}
INT8 EffectiveDexterity( SOLDIERTYPE * pSoldier )
{
INT32 iEffDexterity;
iEffDexterity = pSoldier->bDexterity;
iEffDexterity = EffectStatForBeingDrunk( pSoldier, iEffDexterity );
return( (INT8) iEffDexterity );
}
UINT8 GetPenaltyForFatigue( SOLDIERTYPE *pSoldier )
{
UINT8 ubPercentPenalty;
if ( pSoldier->bBreathMax >= 85 ) ubPercentPenalty = 0;
else if ( pSoldier->bBreathMax >= 70 ) ubPercentPenalty = 10;
else if ( pSoldier->bBreathMax >= 50 ) ubPercentPenalty = 25;
else if ( pSoldier->bBreathMax >= 30 ) ubPercentPenalty = 50;
else if ( pSoldier->bBreathMax >= 15 ) ubPercentPenalty = 75;
else if ( pSoldier->bBreathMax > 0 ) ubPercentPenalty = 90;
else ubPercentPenalty = 100;
return( ubPercentPenalty );
}
void ReducePointsForFatigue( SOLDIERTYPE *pSoldier, UINT16 *pusPoints )
{
*pusPoints -= (*pusPoints * GetPenaltyForFatigue( pSoldier )) / 100;
}
INT32 GetSkillCheckPenaltyForFatigue( SOLDIERTYPE *pSoldier, INT32 iSkill )
{
// use only half the full effect of fatigue for skill checks
return( ( (iSkill * GetPenaltyForFatigue( pSoldier ) ) / 100) / 2 );
}
INT32 SkillCheck( SOLDIERTYPE * pSoldier, INT8 bReason, INT8 bChanceMod )
{
INT32 iSkill;
INT32 iChance, iReportChance;
INT32 iRoll, iMadeItBy;
INT8 bSlot;
INT32 iLoop;
SOLDIERTYPE * pTeamSoldier;
INT8 bBuddyIndex;
BOOLEAN fForceDamnSound = FALSE;
iReportChance = -1;
switch (bReason)
{
case LOCKPICKING_CHECK:
case ELECTRONIC_LOCKPICKING_CHECK:
fForceDamnSound = TRUE;
iSkill = EffectiveMechanical( pSoldier );
if (iSkill == 0)
{
break;
}
// adjust skill based on wisdom (knowledge)
iSkill = iSkill * (EffectiveWisdom( pSoldier ) + 100) / 200;
// and dexterity (clumsy?)
iSkill = iSkill * (EffectiveDexterity( pSoldier ) + 100) / 200;
// factor in experience
iSkill = iSkill + EffectiveExpLevel( pSoldier ) * 3;
if (HAS_SKILL_TRAIT( pSoldier, LOCKPICKING ) )
{
// if we specialize in picking locks...
iSkill += gbSkillTraitBonus[LOCKPICKING] * NUM_SKILL_TRAITS( pSoldier, LOCKPICKING );
}
if (bReason == ELECTRONIC_LOCKPICKING_CHECK && !(HAS_SKILL_TRAIT( pSoldier, ELECTRONICS)) )
{
// if we are unfamiliar with electronics...
iSkill /= 2;
}
// adjust chance based on status of kit
bSlot = FindLocksmithKit( pSoldier );
if (bSlot == NO_SLOT)
{
// this should never happen, but might as well check...
iSkill = 0;
}
iSkill = iSkill * pSoldier->inv[bSlot].bStatus[0] / 100;
break;
case ATTACHING_DETONATOR_CHECK:
case ATTACHING_REMOTE_DETONATOR_CHECK:
iSkill = EffectiveExplosive( pSoldier );
if (iSkill == 0)
{
break;
}
iSkill = (iSkill * 3 + EffectiveDexterity( pSoldier ) ) / 4;
if ( bReason == ATTACHING_REMOTE_DETONATOR_CHECK && !(HAS_SKILL_TRAIT( pSoldier, ELECTRONICS )) )
{
iSkill /= 2;
}
break;
case PLANTING_BOMB_CHECK:
case PLANTING_REMOTE_BOMB_CHECK:
iSkill = EffectiveExplosive( pSoldier ) * 7;
iSkill += EffectiveWisdom( pSoldier ) * 2;
iSkill += EffectiveExpLevel( pSoldier ) * 10;
iSkill = iSkill / 10; // bring the value down to a percentage
if ( bReason == PLANTING_REMOTE_BOMB_CHECK && !(HAS_SKILL_TRAIT( pSoldier, ELECTRONICS)) )
{
// deduct only a bit...
iSkill = (iSkill * 3) / 4;
}
// Ok, this is really damn easy, so skew the values...
// e.g. if calculated skill is 84, skewed up to 96
// 51 to 84
// 22 stays as is
iSkill = (iSkill + 100 * (iSkill / 25) ) / (iSkill / 25 + 1);
break;
case DISARM_TRAP_CHECK:
fForceDamnSound = TRUE;
iSkill = EffectiveExplosive( pSoldier ) * 7;
if ( iSkill == 0 )
{
break;
}
iSkill += EffectiveDexterity( pSoldier ) * 2;
iSkill += EffectiveExpLevel( pSoldier ) * 10;
iSkill = iSkill / 10; // bring the value down to a percentage
// penalty based on poor wisdom
iSkill -= (100 - EffectiveWisdom( pSoldier ) ) / 5;
break;
case DISARM_ELECTRONIC_TRAP_CHECK:
fForceDamnSound = TRUE;
iSkill = __max( EffectiveMechanical( pSoldier ) , EffectiveExplosive( pSoldier ) ) * 7;
if ( iSkill == 0 )
{
break;
}
iSkill += EffectiveDexterity( pSoldier ) * 2;
iSkill += EffectiveExpLevel( pSoldier ) * 10;
iSkill = iSkill / 10; // bring the value down to a percentage
// penalty based on poor wisdom
iSkill -= (100 - EffectiveWisdom( pSoldier ) ) / 5;
if ( !(HAS_SKILL_TRAIT( pSoldier, ELECTRONICS )) )
{
iSkill = (iSkill * 3) / 4;
}
break;
case OPEN_WITH_CROWBAR:
// Add for crowbar...
iSkill = EffectiveStrength( pSoldier ) + 20;
fForceDamnSound = TRUE;
break;
case SMASH_DOOR_CHECK:
iSkill = EffectiveStrength( pSoldier );
break;
case UNJAM_GUN_CHECK:
iSkill = 30 + EffectiveMechanical( pSoldier ) / 2;
break;
case NOTICE_DART_CHECK:
// only a max of ~20% chance
iSkill = EffectiveWisdom( pSoldier ) / 10 + EffectiveExpLevel( pSoldier );
break;
case LIE_TO_QUEEN_CHECK:
// competitive check vs the queen's wisdom and leadership... poor guy!
iSkill = 50 * ( EffectiveWisdom( pSoldier ) + EffectiveLeadership( pSoldier ) ) / ( gMercProfiles[ QUEEN ].bWisdom + gMercProfiles[ QUEEN ].bLeadership );
break;
case ATTACHING_SPECIAL_ITEM_CHECK:
case ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK:
iSkill = EffectiveMechanical( pSoldier );
if (iSkill == 0)
{
break;
}
// adjust skill based on wisdom (knowledge)
iSkill = iSkill * (EffectiveWisdom( pSoldier ) + 100) / 200;
// and dexterity (clumsy?)
iSkill = iSkill * (EffectiveDexterity( pSoldier ) + 100) / 200;
// factor in experience
iSkill = iSkill + EffectiveExpLevel( pSoldier ) * 3;
if (bReason == ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK && !(HAS_SKILL_TRAIT( pSoldier, ELECTRONICS)) )
{
// if we are unfamiliar with electronics...
iSkill /= 2;
}
break;
default:
iSkill = 0;
break;
}
iSkill -= GetSkillCheckPenaltyForFatigue( pSoldier, iSkill );
iChance = iSkill + bChanceMod;
switch (bReason)
{
case LOCKPICKING_CHECK:
case ELECTRONIC_LOCKPICKING_CHECK:
case DISARM_TRAP_CHECK:
case DISARM_ELECTRONIC_TRAP_CHECK:
case OPEN_WITH_CROWBAR:
case SMASH_DOOR_CHECK:
case ATTACHING_SPECIAL_ITEM_CHECK:
case ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK:
// for lockpicking and smashing locks, if the chance isn't reasonable
// we set it to 0 so they can never get through the door if they aren't
// good enough
if (iChance < 30)
{
iChance = 0;
break;
}
// else fall through
default:
iChance += GetMoraleModifier( pSoldier );
break;
}
if (iChance > 99)
{
iChance = 99;
}
else if (iChance < 0)
{
iChance = 0;
}
iRoll = PreRandom( 100 );
iMadeItBy = iChance - iRoll;
if (iMadeItBy < 0)
{
if ( (pSoldier->bLastSkillCheck == bReason) && (pSoldier->sGridNo == pSoldier->sSkillCheckGridNo) )
{
pSoldier->ubSkillCheckAttempts++;
if (pSoldier->ubSkillCheckAttempts > 2)
{
if (iChance == 0)
{
// do we realize that we just can't do this?
if ( (100 - (pSoldier->ubSkillCheckAttempts - 2) * 20) < EffectiveWisdom( pSoldier ) )
{
// say "I can't do this" quote
TacticalCharacterDialogue( pSoldier, QUOTE_DEFINITE_CANT_DO );
return( iMadeItBy );
}
}
}
}
else
{
pSoldier->bLastSkillCheck = bReason;
pSoldier->ubSkillCheckAttempts = 1;
pSoldier->sSkillCheckGridNo = pSoldier->sGridNo;
}
if ( fForceDamnSound || Random( 100 ) < 40 )
{
switch( bReason )
{
case UNJAM_GUN_CHECK:
case NOTICE_DART_CHECK:
case LIE_TO_QUEEN_CHECK:
// silent check
break;
default:
DoMercBattleSound( pSoldier, BATTLE_SOUND_CURSE1 );
break;
}
}
}
else
{
// A buddy might make a positive comment based on our success;
// Increase the chance for people with higher skill and for more difficult tasks
iChance = 15 + iSkill / 20 + (-bChanceMod) / 20;
if (iRoll < iChance)
{
// If a buddy of this merc is standing around nearby, they'll make a positive comment.
iLoop = gTacticalStatus.Team[ gbPlayerNum ].bFirstID;
for ( pTeamSoldier = MercPtrs[ iLoop ]; iLoop <= gTacticalStatus.Team[ gbPlayerNum ].bLastID; iLoop++,pTeamSoldier++ )
{
if ( OK_INSECTOR_MERC( pTeamSoldier ) )
{
bBuddyIndex = WhichBuddy( pTeamSoldier->ubProfile, pSoldier->ubProfile );
if (bBuddyIndex >= 0 && SpacesAway( pSoldier->sGridNo, pTeamSoldier->sGridNo ) < 15)
{
switch( bBuddyIndex )
{
case 0:
// buddy #1 did something good!
TacticalCharacterDialogue( pTeamSoldier, QUOTE_BUDDY_1_GOOD );
break;
case 1:
// buddy #2 did something good!
TacticalCharacterDialogue( pTeamSoldier, QUOTE_BUDDY_2_GOOD );
break;
case 2:
// learn to like buddy did something good!
TacticalCharacterDialogue( pTeamSoldier, QUOTE_LEARNED_TO_LIKE_WITNESSED );
break;
default:
break;
}
}
}
}
}
}
return( iMadeItBy );
}
INT8 CalcTrapDetectLevel( SOLDIERTYPE * pSoldier, BOOLEAN fExamining )
{
// return the level of trap which the guy is able to detect
INT8 bDetectLevel;
// formula: 1 pt for every exp_level
// plus 1 pt for every 40 explosives
// less 1 pt for every 20 wisdom MISSING
bDetectLevel = EffectiveExpLevel( pSoldier );
bDetectLevel += (EffectiveExplosive( pSoldier ) / 40);
bDetectLevel -= ((100 - EffectiveWisdom( pSoldier ) ) / 20);
// if the examining flag is true, this isn't just a casual glance
// and the merc should have a higher chance
if (fExamining)
{
bDetectLevel += (INT8) PreRandom(bDetectLevel / 3 + 2);
}
// if substantially bleeding, or still in serious shock, randomly lower value
if ((pSoldier->bBleeding > 20) || (pSoldier->bShock > 1))
{
bDetectLevel -= (INT8) PreRandom(3);
}
if (bDetectLevel < 1)
{
bDetectLevel = 1;
}
return( bDetectLevel );
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef __SKILL_CHECK_H
#define __SKILL_CHECK_H
#include "types.h"
#include "Soldier Control.h"
extern void ReducePointsForFatigue( SOLDIERTYPE *pSoldier, UINT16 *pusPoints );
extern INT32 GetSkillCheckPenaltyForFatigue( SOLDIERTYPE *pSoldier, INT32 iSkill );
extern INT32 SkillCheck( SOLDIERTYPE *pSoldier, INT8 bReason, INT8 bDifficulty );
extern INT8 CalcTrapDetectLevel( SOLDIERTYPE *pSoldier, BOOLEAN fExamining );
extern INT8 EffectiveStrength( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveWisdom( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveAgility( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveMechanical( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveExplosive( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveLeadership( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveMarksmanship( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveDexterity( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveExpLevel( SOLDIERTYPE *pSoldier );
extern INT8 EffectiveMedical( SOLDIERTYPE *pSoldier );
enum SkillChecks
{
NO_CHECK = 0,
LOCKPICKING_CHECK,
ELECTRONIC_LOCKPICKING_CHECK,
ATTACHING_DETONATOR_CHECK,
ATTACHING_REMOTE_DETONATOR_CHECK,
PLANTING_BOMB_CHECK,
PLANTING_REMOTE_BOMB_CHECK,
OPEN_WITH_CROWBAR,
SMASH_DOOR_CHECK,
DISARM_TRAP_CHECK,
UNJAM_GUN_CHECK,
NOTICE_DART_CHECK,
LIE_TO_QUEEN_CHECK,
ATTACHING_SPECIAL_ITEM_CHECK,
ATTACHING_SPECIAL_ELECTRONIC_ITEM_CHECK,
DISARM_ELECTRONIC_TRAP_CHECK,
} ;
#endif
File diff suppressed because it is too large Load Diff
+63
View File
@@ -0,0 +1,63 @@
#ifndef _SOLDIER_ADD_H
#define _SOLDIER_ADD_H
#include "Soldier Control.h"
// Finds a gridno given a sweet spot
// Returns a good direction too!
UINT16 FindGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection );
// Ensures a good path.....
UINT16 FindGridNoFromSweetSpotThroughPeople( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection );
// Returns a good sweetspot but not the swetspot!
UINT16 FindGridNoFromSweetSpotExcludingSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection );
UINT16 FindGridNoFromSweetSpotExcludingSweetSpotInQuardent( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection, INT8 ubQuardentDir );
// Finds a gridno near a sweetspot but a random one!
UINT16 FindRandomGridNoFromSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection );
// Finds a sweetspot but excluding this one!
UINT16 FindRandomGridNoFromSweetSpotExcludingSweetSpot( SOLDIERTYPE *pSoldier, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection );
// Adds a soldier ( already created in mercptrs[] array )!
// Finds a good placement based on data in the loaded sector and if they are enemy's or not, etc...
BOOLEAN AddSoldierToSector( UINT8 ubID );
BOOLEAN AddSoldierToSectorNoCalculateDirection( UINT8 ubID );
BOOLEAN AddSoldierToSectorNoCalculateDirectionUseAnimation( UINT8 ubID, UINT16 usAnimState, UINT16 usAnimCode );
// IsMercOnTeam() checks to see if the passed in Merc Profile ID is currently on the player's team
BOOLEAN IsMercOnTeam(UINT8 ubMercID);
// requires non-intransit assignment, too
BOOLEAN IsMercOnTeamAndInOmertaAlready(UINT8 ubMercID);
// ATE: Added for contract renewals
BOOLEAN IsMercOnTeamAndAlive(UINT8 ubMercID);
// ATE: Added for contract renewals
BOOLEAN IsMercOnTeamAndInOmertaAlreadyAndAlive(UINT8 ubMercID);
// GetSoldierIDFromMercID() Gets the Soldier ID from the Merc Profile ID, else returns -1
INT16 GetSoldierIDFromMercID(UINT8 ubMercID);
UINT16 FindGridNoFromSweetSpotWithStructData( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT16 sSweetGridNo, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc );
/*
void SoldierInSectorSleep( SOLDIERTYPE *pSoldier, INT16 sGridNo );
*/
UINT16 FindGridNoFromSweetSpotWithStructDataFromSoldier( SOLDIERTYPE *pSoldier, UINT16 usAnimState, INT8 ubRadius, UINT8 *pubDirection, BOOLEAN fClosestToMerc, SOLDIERTYPE *pSrcSoldier );
void SoldierInSectorPatient( SOLDIERTYPE *pSoldier, INT16 sGridNo );
void SoldierInSectorDoctor( SOLDIERTYPE *pSoldier, INT16 sGridNo );
void SoldierInSectorRepair( SOLDIERTYPE *pSoldier, INT16 sGridNo );
BOOLEAN CanSoldierReachGridNoInGivenTileLimit( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT16 sMaxTiles, INT8 bLevel );
#endif
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
#ifndef __SOLDIER_ANI_H
#define __SOLDIER_ANI_H
BOOLEAN AdjustToNextAnimationFrame( SOLDIERTYPE *pSoldier );
BOOLEAN CheckForAndHandleSoldierDeath( SOLDIERTYPE *pSoldier, BOOLEAN *pfMadeCorpse );
BOOLEAN CheckForAndHandleSoldierDyingNotFromHit( SOLDIERTYPE *pSoldier );
BOOLEAN HandleSoldierDeath( SOLDIERTYPE *pSoldier , BOOLEAN *pfMadeCorpse );
BOOLEAN OKFallDirection( SOLDIERTYPE *pSoldier, INT16 sGridNo, INT8 bLevel, INT8 bTestDirection, UINT16 usAnimState );
BOOLEAN HandleCheckForDeathCommonCode( SOLDIERTYPE *pSoldier );
void KickOutWheelchair( SOLDIERTYPE *pSoldier );
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+233
View File
@@ -0,0 +1,233 @@
#ifndef _SOLDIER_CREATE_H
#define _SOLDIER_CREATE_H
#include "Animation Cache.h"
#include "Timer Control.h"
#include "vobject.h"
#include "Overhead Types.h"
#include "Item Types.h"
#include "soldier control.h"
#define SOLDIER_CREATE_AUTO_TEAM -1
//Kris:
//This value is the total maximum number of slots in a map.
//Players 20
//Enemies 32
//Creatures 32
//Rebels 32
//Civilians 32
//Total 148
#define MAX_INDIVIDUALS 148
//Kris: SERIALIZING INFORMATION
//All maps must have:
// -MAPCREATE_STRUCT
// MAPCREATE_STRUCT.ubNumIndividuals determines how many BASIC_SOLDIERCREATE_STRUCTs there are
// -The BASIC_SOLDIERCREATE_STRUCTS are saved contiguously, but if any of them
// fDetailedPlacement set, then there is a SOLDIERCREATE_STRUCT saved immediately after.
//These are the placement slots used by the editor to define where characters are in a map, what
//they are, what team they are on, personality traits, etc. The Merc section of the editor is
//what is used to define these values.
typedef struct
{
BOOLEAN fDetailedPlacement; //Specialized information. Has a counterpart containing all info.
UINT16 usStartingGridNo; //Where the placement position is.
INT8 bTeam; //The team this individual is part of.
INT8 bRelativeAttributeLevel;
INT8 bRelativeEquipmentLevel;
INT8 bDirection; //1 of 8 values (always mandatory)
INT8 bOrders;
INT8 bAttitude;
INT8 bBodyType; //up to 128 body types, -1 means random
INT16 sPatrolGrid[ MAXPATROLGRIDS ]; //possible locations to visit, patrol, etc.
INT8 bPatrolCnt;
BOOLEAN fOnRoof;
UINT8 ubSoldierClass; //army, administrator, elite
UINT8 ubCivilianGroup;
BOOLEAN fPriorityExistance; //These slots are used first
BOOLEAN fHasKeys;
INT8 PADDINGSLOTS[ 14 ];
} BASIC_SOLDIERCREATE_STRUCT; //50 bytes
typedef struct
{
//Bulletproofing so static detailed placements aren't used to tactically create soldiers.
//Used by editor for validation purposes.
BOOLEAN fStatic;
//Profile information used for special NPCs and player mercs.
UINT8 ubProfile;
BOOLEAN fPlayerMerc;
BOOLEAN fPlayerPlan;
BOOLEAN fCopyProfileItemsOver;
//Location information
INT16 sSectorX;
INT16 sSectorY;
INT8 bDirection;
INT16 sInsertionGridNo;
// Can force a team, but needs flag set
INT8 bTeam;
INT8 bBodyType;
//Orders and attitude settings
INT8 bAttitude;
INT8 bOrders;
//Attributes
INT8 bLifeMax;
INT8 bLife;
INT8 bAgility;
INT8 bDexterity;
INT8 bExpLevel;
INT8 bMarksmanship;
INT8 bMedical;
INT8 bMechanical;
INT8 bExplosive;
INT8 bLeadership;
INT8 bStrength;
INT8 bWisdom;
INT8 bMorale;
INT8 bAIMorale;
//Inventory
OBJECTTYPE Inv[ NUM_INV_SLOTS ];
//Palette information for soldiers.
PaletteRepID HeadPal;
PaletteRepID PantsPal;
PaletteRepID VestPal;
PaletteRepID SkinPal;
PaletteRepID MiscPal;
//Waypoint information for patrolling
INT16 sPatrolGrid[ MAXPATROLGRIDS ];
INT8 bPatrolCnt;
//Kris: Additions November 16, 1997 (padding down to 129 from 150)
BOOLEAN fVisible;
UINT16 name[ 10 ];
UINT8 ubSoldierClass; //army, administrator, elite
BOOLEAN fOnRoof;
INT8 bSectorZ;
SOLDIERTYPE *pExistingSoldier;
BOOLEAN fUseExistingSoldier;
UINT8 ubCivilianGroup;
BOOLEAN fKillSlotIfOwnerDies;
UINT8 ubScheduleID;
BOOLEAN fUseGivenVehicle;
INT8 bUseGivenVehicleID;
BOOLEAN fHasKeys;
INT8 bPadding[115];
} SOLDIERCREATE_STRUCT;
//Original functions currently used throughout the game.
BOOLEAN TacticalRemoveSoldier( UINT16 usSoldierIndex );
BOOLEAN TacticalRemoveSoldierPointer( SOLDIERTYPE *pSoldier, BOOLEAN fRemoveVehicle );
INT8 CalcDifficultyModifier( UINT8 ubSoldierClass );
void RandomizeNewSoldierStats( SOLDIERCREATE_STRUCT *pCreateStruct );
//Kris:
//Modified return type from BOOLEAN to SOLDIERTYPE*
SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *pubID );
//Randomly generated enemies used by strategic AI.
SOLDIERTYPE* TacticalCreateAdministrator();
SOLDIERTYPE* TacticalCreateEliteEnemy();
SOLDIERTYPE* TacticalCreateArmyTroop();
SOLDIERTYPE* TacticalCreateMilitia( UINT8 ubMilitiaClass );
SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType );
// randomly generates a relative level rating (attributes or equipment)
void RandomizeRelativeLevel( INT8 *pbRelLevel, UINT8 ubSoldierClass );
// get the pythag. distance from the passed sector to the palace..
UINT8 GetPythDistanceFromPalace( INT16 sSectorX, INT16 sSectorY );
//These following functions are currently used exclusively by the editor.
//Now, this will be useful for the strategic AI.
//Definitions:
//Soldier (s): Currently in the game, but subject to modifications. The editor has the capability to
// modify soldier attributes on the fly for testing purposes.
//BasicPlacement (bp): A BASIC_SOLDIERCREATE_STRUCT that contains compact, very general, information about
// a soldier. The BasicPlacement is then used to generate a DetailedPlacement before creating a soldier.
// Most of the soldiers saved in the maps will be saved in this manner.
//DetailedPlacement (pp): A SOLDIERCREATE_STRUCT ready to be passed to TacticalCreateSoldier to generate
// and add a new soldier to the world. The DetailedPlacement contains all of the necessary information
// to do this. This information won't be saved in maps. In most cases, only very few attributes are static,
// and the rest are generated at runtime. Because of this situation, saved detailed placements must be in a
// different format.
//StaticDetailedPlacement (spp): A hybrid version of the DetailedPlacement. This is the information saved in
// the map via the editor. When loaded, this information is converted to a normal detailed placement, but
// must also use the BasicPlacement information to complete this properly. Once the conversion is complete,
// the static information is lost. This gives us complete flexibility. The basic placements contain relative
// values that work in conjunction with the strategic AI's relative values to generate soldiers. In no
// circumstances will static detailed placements be used outside of the editor. Note, that this hybrid version
// uses the identical structure as detailed placements. All non-static values are set to -1.
//Used to generate a detailed placement from a basic placement. This assumes that the detailed placement
//doesn't exist, meaning there are no static attributes. This is called when you wish to convert a basic
//placement into a detailed placement just before creating a soldier.
void CreateDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *pp, BASIC_SOLDIERCREATE_STRUCT *bp );
//Used exclusively by the editor when the user wishes to change a basic placement into a detailed placement.
//Because the intention is to make some of the attributes static, all of the information that can be generated
//are defaulted to -1. When an attribute is made to be static, that value in replaced by the new static value.
//This information is NOT compatible with TacticalCreateSoldier. Before doing so, you must first convert the
//static detailed placement to a regular detailed placement.
void CreateStaticDetailedPlacementGivenBasicPlacementInfo( SOLDIERCREATE_STRUCT *spp, BASIC_SOLDIERCREATE_STRUCT *bp );
//When you are ready to generate a soldier with a static detailed placement slot, this function will generate
//the proper priority placement slot given the static detailed placement and it's accompanying basic placment.
//For the purposes of merc editing, the static detailed placement is preserved.
void CreateDetailedPlacementGivenStaticDetailedPlacementAndBasicPlacementInfo(
SOLDIERCREATE_STRUCT *pp, SOLDIERCREATE_STRUCT *spp, BASIC_SOLDIERCREATE_STRUCT *bp );
//Used to update a existing soldier's attributes with the new static detailed placement info. This is used
//by the editor upon exiting the editor into the game, to update the existing soldiers with new information.
//This gives flexibility of testing mercs. Upon entering the editor again, this call will reset all the
//mercs to their original states.
void UpdateSoldierWithStaticDetailedInformation( SOLDIERTYPE *s, SOLDIERCREATE_STRUCT *spp );
//In the case of setting a profile ID in order to extract a soldier from the profile array, we
//also want to copy that information to the static detailed placement, for editor viewing purposes.
void UpdateStaticDetailedPlacementWithProfileInformation( SOLDIERCREATE_STRUCT *spp, UINT8 ubProfile );
//When the editor modifies the soldier's relative attribute level,
//this function is called to update that information.
void ModifySoldierAttributesWithNewRelativeLevel( SOLDIERTYPE *s, INT8 bLevel );
// Force the soldier to be a different ID
void ForceSoldierProfileID( SOLDIERTYPE *pSoldier, UINT8 ubProfileID );
void GeneratePaletteForSoldier( SOLDIERTYPE *pSoldier, UINT8 ubSoldierClass );
void QuickCreateProfileMerc( INT8 bTeam, UINT8 ubProfileID );
BOOLEAN InternalTacticalRemoveSoldier( UINT16 usSoldierIndex, BOOLEAN fRemoveVehicle );
//SPECIAL! Certain events in the game can cause profiled NPCs to become enemies. The two cases are
//adding Mike and Iggy. We will only add one NPC in any given combat and the conditions for setting
//the associated facts are done elsewhere. The function will set the profile for the SOLDIERCREATE_STRUCT
//and the rest will be handled automatically so long the ubProfile field doesn't get changed.
//NOTE: We don't want to add Mike or Iggy if this is being called from autoresolve!
void OkayToUpgradeEliteToSpecialProfiledEnemy( SOLDIERCREATE_STRUCT *pp );
extern BOOLEAN gfProfiledEnemyAdded; //needs to be saved (used by the above function)
#endif
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More