mirror of
https://github.com/1dot13/source.git
synced 2026-07-29 13:52:17 +02:00
- New Feature: Tactical recruitment allows recruiting civilians as volunteers.
See http://thepit.ja-galaxy-forum.com/index.php?t=msg&goto=341335&#msg_341335 This is fully savegame compatible. GameDir <= r2250 is recommended. - Fix: prisoners do not talk. git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@7886 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
@@ -438,6 +438,10 @@ typedef enum
|
||||
PRISONER_MAX,
|
||||
} PrisonerType;
|
||||
|
||||
// -------- added by Flugente: sector info flags --------
|
||||
// easier than adding 32 differently named variables. DO NOT CHANGE THEM, UNLESS YOU KNOW WHAT YOU ARE DOING!!!
|
||||
#define SECTORINFO_VOLUNTEERS_RECENTLY_RECRUITED 0x01 //1 // we recruited volunteers here. Until this flag is removed, newly created civilians wont be potential volunteers anymore
|
||||
|
||||
typedef struct SECTORINFO
|
||||
{
|
||||
//information pertaining to this sector
|
||||
@@ -495,7 +499,7 @@ typedef struct SECTORINFO
|
||||
// HEADROCK HAM 3.6: Flag to determine whether enemy units in this sector can be seen, and whether their numbers
|
||||
// should be displayed. One filler was replaced to make room.
|
||||
UINT8 ubDetectionLevel;
|
||||
UINT8 bFiller2;
|
||||
UINT8 usSectorInfoFlag; // a flagmask
|
||||
UINT8 bFiller3;
|
||||
|
||||
UINT32 uiNumberOfWorldItemsInTempFileThatCanBeSeenByPlayer;
|
||||
|
||||
@@ -824,6 +824,23 @@ void HandleNPCSystemEvent( UINT32 uiEvent )
|
||||
|
||||
void HandleEarlyMorningEvents( void )
|
||||
{
|
||||
// Flugente: no reason to put this into LUA
|
||||
for ( UINT8 sX = 1; sX < MAP_WORLD_X - 1; ++sX )
|
||||
{
|
||||
for ( UINT8 sY = 1; sY < MAP_WORLD_X - 1; ++sY )
|
||||
{
|
||||
UINT8 sector = SECTOR( sX, sY );
|
||||
|
||||
SECTORINFO *pSectorInfo = &(SectorInfo[sector]);
|
||||
|
||||
// A flag prevents us from exploiting the civilian recruitment mechanic. Every x hours, we reset it
|
||||
if ( pSectorInfo )
|
||||
{
|
||||
pSectorInfo->usSectorInfoFlag &= ~SECTORINFO_VOLUNTEERS_RECENTLY_RECRUITED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LUA_STRATEGY_EVENT_HANDLER
|
||||
LetLuaHandleEarlyMorningEvents(0);
|
||||
#else
|
||||
|
||||
@@ -361,7 +361,7 @@ enum
|
||||
UNNAMED_CIV_GROUP_19,
|
||||
ASSASSIN_CIV_GROUP, // Flugente: enemy assassins belong to this group
|
||||
POW_PRISON_CIV_GROUP, // Flugente: prisoners of war the player caught are in this group
|
||||
UNNAMED_CIV_GROUP_22,
|
||||
VOLUNTEER_CIV_GROUP, // Flugente: civilians that the player recruited
|
||||
UNNAMED_CIV_GROUP_23,
|
||||
UNNAMED_CIV_GROUP_24,
|
||||
UNNAMED_CIV_GROUP_25,
|
||||
|
||||
@@ -3839,6 +3839,10 @@ void HandleNPCTeamMemberDeath( SOLDIERTYPE *pSoldierOld )
|
||||
// Flugente: if this was a prisoner of war, reduce their sector count by 1
|
||||
if ( pSoldierOld->usSoldierFlagMask & SOLDIER_POW_PRISON )
|
||||
KillOnePrisoner( &SectorInfo[ SECTOR( gWorldSectorX, gWorldSectorY ) ] );
|
||||
|
||||
// If this was a volunteer, then we definetly reduce our volunteer pool
|
||||
if ( pSoldierOld->bTeam == CIV_TEAM && pSoldierOld->ubCivilianGroup == VOLUNTEER_CIV_GROUP )
|
||||
AddVolunteers( -1 );
|
||||
}
|
||||
else if ( pSoldierOld->bTeam == MILITIA_TEAM )
|
||||
{
|
||||
|
||||
@@ -118,6 +118,7 @@
|
||||
#include "Tactical Save.h" // added by Flugente for AddItemsToUnLoadedSector()
|
||||
#include "LightEffects.h" // added by Flugente for CreatePersonalLight()
|
||||
#include "DynamicDialogue.h" // added by Flugente for HandleDynamicOpinions()
|
||||
#include "strategic town loyalty.h" // added by Flugente for gTownLoyalty
|
||||
|
||||
//forward declarations of common classes to eliminate includes
|
||||
class OBJECTTYPE;
|
||||
@@ -20437,14 +20438,16 @@ BOOLEAN SOLDIERTYPE::PlayerSoldierStartTalking( UINT8 ubTargetID, BOOLEAN fValid
|
||||
apsDeducted = TRUE;
|
||||
|
||||
// Flugente: if we are talking to an enemy, we have the option to offer them surrender...
|
||||
if ( (pTSoldier->bTeam == ENEMY_TEAM || (pTSoldier->bTeam == CIV_TEAM && zCivGroupName[pTSoldier->ubCivilianGroup].fCanBeCaptured) )
|
||||
&& (gGameExternalOptions.fEnemyCanSurrender || gGameExternalOptions.fPlayerCanAsktoSurrender) )
|
||||
if ( (gGameExternalOptions.fEnemyCanSurrender || gGameExternalOptions.fPlayerCanAsktoSurrender) && pTSoldier->CanBeCaptured( ) )
|
||||
{
|
||||
HandleSurrenderOffer( pTSoldier );
|
||||
return(FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flugente: if this guy is a potential volunteer, we might be able to sway him
|
||||
HandleVolunteerRecruitment( this, pTSoldier );
|
||||
|
||||
StartCivQuote( pTSoldier );
|
||||
return(FALSE);
|
||||
}
|
||||
@@ -22806,3 +22809,77 @@ UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OB
|
||||
return uiMedcost;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Flugente: decide whether pRecruiter can successfully recruit pTarget to be a volunteer
|
||||
void HandleVolunteerRecruitment( SOLDIERTYPE* pRecruiter, SOLDIERTYPE* pTarget )
|
||||
{
|
||||
if ( !pRecruiter || pRecruiter->bTeam != OUR_TEAM )
|
||||
return;
|
||||
|
||||
// potential recruit must be a civilain NPC of no other affilation, no kids
|
||||
if ( !pTarget || pTarget->bTeam != CIV_TEAM || pTarget->ubProfile != NO_PROFILE || pTarget->ubCivilianGroup != NON_CIV_GROUP || pTarget->ubBodyType > DRESSCIV )
|
||||
return;
|
||||
|
||||
// target must unharmed
|
||||
if ( pTarget->bCollapsed || pTarget->bBreathCollapsed || pTarget->stats.bLife < pTarget->stats.bLifeMax )
|
||||
return;
|
||||
|
||||
// target must be friendly
|
||||
if ( !pTarget->aiData.bNeutral )
|
||||
return;
|
||||
|
||||
// Set a flag in this sector. This flag is removed every x hours. As long as it exists, newly created civilians won't be potential volunteers
|
||||
// this is simply there to prevent the exploit of reloading the sector repeatedly and 'harvesting' volunteers.
|
||||
// we do this even if we do not recruit this guy - otherwise the player could reload the sector over and over again until he find a volunteer
|
||||
UINT8 sector = SECTOR( pTarget->sSectorX, pTarget->sSectorY );
|
||||
|
||||
SECTORINFO *pSectorInfo = &(SectorInfo[sector]);
|
||||
|
||||
if ( pSectorInfo )
|
||||
{
|
||||
pSectorInfo->usSectorInfoFlag |= SECTORINFO_VOLUNTEERS_RECENTLY_RECRUITED;
|
||||
}
|
||||
|
||||
// can we recruit him in the first place?
|
||||
if ( pTarget->usSoldierFlagMask2 & SOLDIER_POTENTIAL_VOLUNTEER )
|
||||
{
|
||||
// if sector not under our control, has enemies in it, or is currently in combat mode
|
||||
if ( !SectorOursAndPeaceful( pTarget->sSectorX, pTarget->sSectorY, pTarget->bSectorZ ) )
|
||||
return;
|
||||
|
||||
// if this a town sector, min loyalty is required
|
||||
// other sectors do not have a loyalty rating. This is okay here, as then the player has an incentive to try his luck outside of towns
|
||||
UINT8 ubTownID = StrategicMap[CALCULATE_STRATEGIC_INDEX( pTarget->sSectorX, pTarget->sSectorY )].bNameId;
|
||||
if ( ubTownID != BLANK_SECTOR )
|
||||
{
|
||||
if ( gTownLoyalty[ubTownID].ubRating < gGameExternalOptions.iMinLoyaltyToTrain )
|
||||
return;
|
||||
}
|
||||
|
||||
// recruiter ability
|
||||
FLOAT leadershipfactor = EffectiveLeadership( pRecruiter ) / 100.0;
|
||||
|
||||
// bonus for assertive characters
|
||||
if ( gMercProfiles[pRecruiter->ubProfile].bCharacterTrait == CHAR_TRAIT_ASSERTIVE )
|
||||
leadershipfactor *= 1.05;
|
||||
|
||||
FLOAT recruitmodifier = (100 + pRecruiter->GetBackgroundValue( BG_PERC_APPROACH_RECRUIT )) / 100.0;
|
||||
|
||||
FLOAT rating = leadershipfactor * recruitmodifier * gMercProfiles[pRecruiter->ubProfile].usApproachFactor[3];
|
||||
|
||||
// hard check. We do not use Chance()-base functions, as then the player would have to repeat this over and over again to be sure that someone is not a volunteer
|
||||
if ( rating > 70.0 )
|
||||
{
|
||||
// success! remove the flag, put this guy in a new group, and add one volunteer
|
||||
pTarget->usSoldierFlagMask2 &= ~SOLDIER_POTENTIAL_VOLUNTEER;
|
||||
|
||||
pTarget->ubCivilianGroup = VOLUNTEER_CIV_GROUP;
|
||||
|
||||
AddVolunteers( 1 );
|
||||
|
||||
// the recruiter gets a bit of experience
|
||||
StatChange( pRecruiter, LDRAMT, 8, TRUE );
|
||||
StatChange( pRecruiter, EXPERAMT, 5, TRUE );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,6 +408,7 @@ enum
|
||||
#define SOLDIER_INTERROGATE_GENERAL 0x00000080 //128 // interrogate generals
|
||||
|
||||
#define SOLDIER_INTERROGATE_CIVILIAN 0x00000100 //256 // interrogate civilian
|
||||
#define SOLDIER_POTENTIAL_VOLUNTEER 0x00000200 //512 // this civilian _might_ join us as a volunteer if conditions are right
|
||||
|
||||
#define SOLDIER_INTERROGATE_ALL 0x000001F8 // all interrogation flags
|
||||
// ----------------------------------------------------------------
|
||||
@@ -2724,6 +2725,9 @@ void SetDamageDisplayCounter(SOLDIERTYPE* pSoldier);
|
||||
// SANDRO - This whole procedure was merged with the surgery ability of the doctor trait
|
||||
UINT32 VirtualSoldierDressWound( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pVictim, OBJECTTYPE *pKit, INT16 sKitPts, INT16 sStatus, BOOLEAN fOnSurgery );
|
||||
|
||||
// Flugente: decide whether pRecruiter can successfully recruit pTarget to be a volunteer
|
||||
void HandleVolunteerRecruitment( SOLDIERTYPE* pRecruiter, SOLDIERTYPE* pTarget );
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -1137,7 +1137,22 @@ SOLDIERTYPE* TacticalCreateSoldier( SOLDIERCREATE_STRUCT *pCreateStruct, UINT8 *
|
||||
default:
|
||||
Soldier.aiData.bNormalSmell = NORMAL_HUMAN_SMELL_STRENGTH;
|
||||
break;
|
||||
}
|
||||
|
||||
// Flugente: under certain conditions, we can recruit civilians
|
||||
if ( Soldier.bTeam == CIV_TEAM && Soldier.ubProfile == NO_PROFILE && Soldier.ubCivilianGroup == NON_CIV_GROUP && Soldier.ubBodyType <= DRESSCIV )
|
||||
{
|
||||
// there has to officially be an outbreak in this sector - if we don't know of a disease, we cannot treat it!
|
||||
UINT8 sector = SECTOR( Soldier.sSectorX, Soldier.sSectorY );
|
||||
|
||||
SECTORINFO *pSectorInfo = &(SectorInfo[sector]);
|
||||
|
||||
// only allow us to be a volunteer if this isn't blocked
|
||||
if ( pSectorInfo && !(pSectorInfo->usSectorInfoFlag & SECTORINFO_VOLUNTEERS_RECENTLY_RECRUITED) )
|
||||
{
|
||||
if ( Chance(10) )
|
||||
Soldier.usSoldierFlagMask2 |= SOLDIER_POTENTIAL_VOLUNTEER;
|
||||
}
|
||||
}
|
||||
|
||||
if( guiCurrentScreen != AUTORESOLVE_SCREEN )
|
||||
|
||||
Reference in New Issue
Block a user