- Prisoners of war are now spawned in prison sectors. They have fitting dialogue etc. Harming them slightly lowers global loyalty.

- Prisoner system: added ini options that allow display of surrender strength sum, and externalised surrender strength modifier
- Fix: wrong assignment string in strategic view

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5895 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
Flugente
2013-03-05 01:02:59 +00:00
parent ca20403bc4
commit 36f7399d3b
23 changed files with 319 additions and 13 deletions
+3
View File
@@ -480,12 +480,15 @@ OBJECTTYPE* GetExternalFeedingObject(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject
BOOLEAN DeductBulletViaExternalFeeding(SOLDIERTYPE* pSoldier, OBJECTTYPE * pObject);
#define MAX_PRISON_ROOMS 16
// Flugente: additional xml data for sectors
typedef struct
{
UINT8 usWaterType; // type of water source in this sector
UINT16 usNaturalDirt; // extra dirt percentage when firing in this sector
UINT8 usCurfewValue; // determines wether mercs disguising as civilian are automatically discovered (certain sectors are 'restricted' to civilians)
UINT16 usPrisonRoomNumber[MAX_PRISON_ROOMS]; // room numbers of prisons
} SECTOR_EXT_DATA;
// get dirt increase for object with attachments, fConsiderAmmo: with ammo
+1 -1
View File
@@ -359,7 +359,7 @@ enum
UNNAMED_CIV_GROUP_18,
UNNAMED_CIV_GROUP_19,
ASSASSIN_CIV_GROUP, // Flugente: enemy assassins belong to this group
UNNAMED_CIV_GROUP_21,
POW_PRISON_CIV_GROUP, // Flugente: prisoners of war the player caught are in this group
UNNAMED_CIV_GROUP_22,
UNNAMED_CIV_GROUP_23,
UNNAMED_CIV_GROUP_24,
+19 -1
View File
@@ -3824,6 +3824,15 @@ void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld )
HandleMurderOfCivilian( pSoldierOld, pSoldierOld->flags.fIntendedTarget );
}
}
// Flugente: if this was a prisoner of war, reduce their sector count by 1
if ( pSoldierOld->bSoldierFlagMask & SOLDIER_POW_PRISON )
{
// get sector
SECTORINFO *pSector = &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ];
if ( pSector )
pSector->uiNumberOfPrisonersOfWar = max(0, pSector->uiNumberOfPrisonersOfWar - 1);
}
}
else if ( pSoldierOld->bTeam == MILITIA_TEAM )
{
@@ -8604,6 +8613,11 @@ BOOLEAN ProcessImplicationsOfPCAttack( SOLDIERTYPE * pSoldier, SOLDIERTYPE ** pp
}
}
}
// Flugente: if we attack prisoners, the local support might wane, as we turned out to be cruel oppressors, not liberators
else if ( (pTarget->bTeam == CIV_TEAM) && (pTarget->ubCivilianGroup == POW_PRISON_CIV_GROUP) )
{
HandleGlobalLoyaltyEvent( GLOBAL_LOYALTY_PRISONERS_TORTURED, gWorldSectorX, gWorldSectorY, gbWorldSectorZ );
}
else if (pTarget->bTeam == CREATURE_TEAM && pTarget->ubBodyType == BLOODCAT && pTarget->aiData.bNeutral)
{
// Attacked a bloodcat.
@@ -10130,8 +10144,12 @@ void PrisonerSurrenderMessageBoxCallBack( UINT8 ubExitValue )
}
}
// print out values
if ( gGameExternalOptions.fDisplaySurrenderSValues )
ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"PlayerStrength : %d Enemystrength: %6.0f", playersidestrength, gGameExternalOptions.fSurrenderMultiplier * enemysidestrength );
// perhaps this can be fleshed out more, for now, let's see if this is acceptable behaviour
if ( playersidestrength >= 6 * enemysidestrength )
if ( playersidestrength >= gGameExternalOptions.fSurrenderMultiplier * enemysidestrength )
{
// it is enough to simply set all soldiers to captured
firstid = gTacticalStatus.Team[ ENEMY_TEAM ].bFirstID;
+2 -2
View File
@@ -363,8 +363,8 @@ enum
#define SOLDIER_POW 0x00000400 //1024 // we are a prisoner of war
#define SOLDIER_ASSASSIN 0x00000800 //2048 // we are an enemy assassin, and thus we will behave very different from normal enemies
/*#define SOLDIER_EQ_TAKEN 0x00001000 //4096 // this militia's equipment was taken from a sector inventory
#define SOLDIER_EQ_EMPTY 0x00002000 //8192 // this militia has no equipment and is to be equipped from the sector inventory
#define SOLDIER_POW_PRISON 0x00001000 //4096 // this guy is a prisoner of war in a prison sector. SOLDIER_POW refers to people we capture, this refers to people we hold captive
/*#define SOLDIER_EQ_EMPTY 0x00002000 //8192 // this militia has no equipment and is to be equipped from the sector inventory
#define ENEMY_NET_3_LVL_4 0x00004000 //16384
#define ENEMY_NET_4_LVL_4 0x00008000 //32768
+92
View File
@@ -3165,6 +3165,98 @@ void CreateAssassin(UINT8 disguisetype)
}
}
extern UINT16* gusWorldRoomInfo;
extern SECTOR_EXT_DATA SectorExternalData[256][4];
static UINT8 roomcnt = 0;
void CreatePrisonerOfWar()
{
INT32 insertiongridno = NOWHERE;
// get sector data and look fo a fitting room
UINT8 ubSectorId = SECTOR(gWorldSectorX, gWorldSectorY);
if ( ubSectorId >= 0 && ubSectorId < 256 )
{
UINT8 numrooms = 0;
for(UINT8 i = 0; i < MAX_PRISON_ROOMS; ++i)
if ( SectorExternalData[ubSectorId][0].usPrisonRoomNumber[i] > 0)
++numrooms;
++roomcnt;
if ( roomcnt >= numrooms )
roomcnt = 0;
UINT16 room = SectorExternalData[ubSectorId][0].usPrisonRoomNumber[roomcnt];
for ( UINT32 uiLoop = 0; uiLoop < WORLD_MAX; ++uiLoop )
{
if ( (gusWorldRoomInfo[ uiLoop ] == room) )
{
// we have to make sure that the gridno is deep in the room, as otherwise the gridno might be corrected to be on the other side of a wall
if ( gusWorldRoomInfo[ NewGridNo( uiLoop, DirectionInc(NORTH) ) ] == room )
if ( gusWorldRoomInfo[ NewGridNo( uiLoop, DirectionInc(EAST) ) ] == room )
if ( gusWorldRoomInfo[ NewGridNo( uiLoop, DirectionInc(SOUTH) ) ] == room )
if ( gusWorldRoomInfo[ NewGridNo( uiLoop, DirectionInc(WEST) ) ] == room )
{
// check wether this location is sittable
if ( IsLocationSittable( uiLoop, 0 ) )
{
insertiongridno = uiLoop;
break;
}
}
}
}
// invalid gridno? Get out of here
if ( TileIsOutOfBounds(insertiongridno) )
return;
}
SOLDIERCREATE_STRUCT MercCreateStruct;
UINT8 ubID;
static INT8 bPowBodyType = REGMALE;
MercCreateStruct.initialize();
MercCreateStruct.bTeam = CIV_TEAM;
MercCreateStruct.ubProfile = NO_PROFILE;
MercCreateStruct.sSectorX = gWorldSectorX;
MercCreateStruct.sSectorY = gWorldSectorY;
MercCreateStruct.bSectorZ = gbWorldSectorZ;
MercCreateStruct.sInsertionGridNo = insertiongridno;
MercCreateStruct.ubDirection = Random(NUM_WORLD_DIRECTIONS);
MercCreateStruct.bBodyType = bPowBodyType;
++bPowBodyType;
if ( bPowBodyType > REGFEMALE )
bPowBodyType = REGMALE;
RandomizeNewSoldierStats( &MercCreateStruct );
SOLDIERTYPE* pSoldier = TacticalCreateSoldier( &MercCreateStruct, &ubID );
if ( pSoldier )
{
AddSoldierToSector( pSoldier->ubID );
// mark this guy
pSoldier->bSoldierFlagMask |= SOLDIER_POW_PRISON;
// set correct civ group
pSoldier->ubCivilianGroup = POW_PRISON_CIV_GROUP;
// set militia name to further irritate the player
swprintf( pSoldier->name, TacticalStr[ POW_TEAM_MERC_NAME ] );
// So we can see them!
AllTeamsLookForAll(NO_INTERRUPTS);
gTacticalStatus.fCivGroupHostile[ POW_PRISON_CIV_GROUP ] = CIV_GROUP_NEUTRAL;
}
}
void RandomizeRelativeLevel( INT8 *pbRelLevel, UINT8 ubSoldierClass )
{
UINT8 ubLocationModifier = 0;
+2
View File
@@ -430,6 +430,8 @@ SOLDIERTYPE* TacticalCreateCreature( INT8 bCreatureBodyType );
SOLDIERTYPE* TacticalCreateEnemyAssassin(UINT8 disguisetype);
void CreateAssassin(UINT8 disguisetype);
void CreatePrisonerOfWar();
// randomly generates a relative level rating (attributes or equipment)
void RandomizeRelativeLevel( INT8 *pbRelLevel, UINT8 ubSoldierClass );
+64
View File
@@ -918,6 +918,10 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
if ( bTeam == MILITIA_TEAM )
SectorAddAssassins(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
// Flugente: spawn prisoners of war in prison sectors
if ( bTeam == CIV_TEAM )
SectorAddPrisonersofWar(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
//There aren't any basic placements of desired team, so exit.
return ubNumAdded;
}
@@ -965,6 +969,10 @@ UINT8 AddSoldierInitListTeamToWorld( INT8 bTeam, UINT8 ubMaxNum )
if ( bTeam == MILITIA_TEAM )
SectorAddAssassins(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
// Flugente: spawn prisoners of war in prison sectors
if ( bTeam == CIV_TEAM )
SectorAddPrisonersofWar(gWorldSectorX, gWorldSectorY, gbWorldSectorZ);
return ubNumAdded;
}
@@ -2793,3 +2801,59 @@ void SectorAddAssassins( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
++numberofcivs;
}
}
// Flugente: decide wether to create prisoners of war in a sector. Not to be confused with player POWs
void SectorAddPrisonersofWar( INT16 sMapX, INT16 sMapY, INT16 sMapZ )
{
// this needs to be turned on on
if ( !gGameExternalOptions.fAllowPrisonerSystem )
return;
// not in underground sectors
if ( sMapZ > 0 )
return;
// get sector
SECTORINFO *pSector = &SectorInfo[ SECTOR( sMapX, sMapY ) ];
if ( !pSector )
return;
// only continue if there are prisoners in this sector that need to be placed
UINT32 numprisoners = pSector->uiNumberOfPrisonersOfWar;
numprisoners = 30;
if ( !numprisoners )
return;
// count current number of civilians and already placed pows
UINT16 numberofcivs = 0;
UINT16 numberofpows = 0;
SOLDIERTYPE* pTeamSoldier = NULL;
INT32 cnt = gTacticalStatus.Team[ CIV_TEAM ].bFirstID;
INT32 lastid = gTacticalStatus.Team[ CIV_TEAM ].bLastID;
for ( pTeamSoldier = MercPtrs[ cnt ]; cnt < lastid; ++cnt, ++pTeamSoldier)
{
// check if teamsoldier exists in this sector
if ( pTeamSoldier && pTeamSoldier->bActive && pTeamSoldier->bInSector && pTeamSoldier->sSectorX == sMapX && pTeamSoldier->sSectorY == sMapY && pTeamSoldier->bSectorZ == sMapZ )
++numberofcivs;
// count how many pows are already placed
if ( pTeamSoldier->bSoldierFlagMask & SOLDIER_POW_PRISON )
++numberofpows;
}
// we can't spawn if all civilian slots are already taken (we leave a bit of reserve for more important civs)
UINT8 maxcivs = max(0, gGameExternalOptions.ubGameMaximumNumberOfCivilians - 3);
for (UINT8 i = numberofpows; i < numprisoners; ++i)
{
if ( numberofcivs < maxcivs )
{
CreatePrisonerOfWar();
++numberofcivs;
}
else
break;
}
}
+3
View File
@@ -62,4 +62,7 @@ void AddProfilesNotUsingProfileInsertionData();
// Flugente: decide wether to spawn enemy assassins in this sector (not kingpin's hitmen, they are handled elsewhere)
void SectorAddAssassins( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
// Flugente: decide wether to create prisoners of war in a sector. Not to be confused with player POWs
void SectorAddPrisonersofWar( INT16 sMapX, INT16 sMapY, INT16 sMapZ );
#endif