mirror of
https://github.com/1dot13/source.git
synced 2026-08-12 14:10:23 +02:00
New feature: mercs can drag people and corpses
Requires GameDir >= r2386. For more info, see http://thepit.ja-galaxy-forum.com/index.php?t=msg&th=23508&goto=350989&#msg_350989 git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@8474 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+8
-1
@@ -2267,7 +2267,14 @@ void HandleRenderFaceAdjustments( FACETYPE *pFace, BOOLEAN fDisplayBuffer, BOOLE
|
||||
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 28 );
|
||||
bNumRightIcons++;
|
||||
}
|
||||
|
||||
|
||||
// Flugente: drag stuff
|
||||
if ( MercPtrs[pFace->ubSoldierID]->IsDraggingSomeone() )
|
||||
{
|
||||
DoRightIcon( uiRenderBuffer, pFace, sFaceX, sFaceY, bNumRightIcons, 31 );
|
||||
++bNumRightIcons;
|
||||
}
|
||||
|
||||
switch( pSoldier->bAssignment )
|
||||
{
|
||||
CASE_DOCTOR:
|
||||
|
||||
+19
-1
@@ -3087,9 +3087,27 @@ UINT32 GetTotalWeight( SOLDIERTYPE* pSoldier )
|
||||
return uiTotalWeight;
|
||||
}
|
||||
|
||||
UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier )
|
||||
UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier, BOOLEAN fConsiderDragging)
|
||||
{
|
||||
UINT32 uiTotalWeight = GetTotalWeight( pSoldier );
|
||||
|
||||
// Flugente: if we drag someone, add their weight to ours
|
||||
if ( fConsiderDragging && pSoldier->IsDraggingSomeone() )
|
||||
{
|
||||
if (pSoldier->usDragPersonID != NOBODY)
|
||||
{
|
||||
SOLDIERTYPE* pOtherSoldier = MercPtrs[pSoldier->usDragPersonID];
|
||||
|
||||
uiTotalWeight += GetTotalWeight( pOtherSoldier );
|
||||
uiTotalWeight += pOtherSoldier->GetBodyWeight();
|
||||
}
|
||||
else if (pSoldier->sDragCorpseID >= 0)
|
||||
{
|
||||
// just give corpses a flat weight
|
||||
uiTotalWeight += 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
UINT32 uiPercent;
|
||||
UINT32 ubStrengthForCarrying;
|
||||
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ extern BOOLEAN PlaceObjectAtObjectIndex( OBJECTTYPE * pSourceObj, OBJECTTYPE * p
|
||||
UINT16 CalculateAmmoWeight( UINT16 usGunAmmoItem, UINT16 ubShotsLeft );
|
||||
UINT16 CalculateObjectWeight( OBJECTTYPE *pObject );
|
||||
UINT32 GetTotalWeight( SOLDIERTYPE* pSoldier );
|
||||
UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier );
|
||||
UINT32 CalculateCarriedWeight( SOLDIERTYPE * pSoldier, BOOLEAN fConsiderDragging = FALSE );
|
||||
// CHRISL:
|
||||
UINT16 CalculateItemSize( OBJECTTYPE *pObject );
|
||||
|
||||
|
||||
@@ -1767,21 +1767,19 @@ BOOLEAN ExecuteOverhead( )
|
||||
// dAngle = (FLOAT)atan2( dDeltaX, dDeltaY );
|
||||
dAngle = gdRadiansForAngle[ pSoldier->bMovementDirection ];
|
||||
|
||||
FLOAT movementchange = gAnimControl[pSoldier->usAnimState].dMovementChange;
|
||||
|
||||
// For walking, base it on body type!
|
||||
if ( pSoldier->usAnimState == WALKING ||
|
||||
pSoldier->usAnimState == WALKING_WEAPON_RDY ||
|
||||
pSoldier->usAnimState == WALKING_DUAL_RDY ||
|
||||
pSoldier->usAnimState == WALKING_ALTERNATIVE_RDY )
|
||||
{
|
||||
pSoldier->MoveMerc( gubAnimWalkSpeeds[ pSoldier->ubBodyType ].dMovementChange, dAngle, TRUE );
|
||||
|
||||
movementchange = gubAnimWalkSpeeds[pSoldier->ubBodyType].dMovementChange;
|
||||
}
|
||||
else
|
||||
{
|
||||
pSoldier->MoveMerc( gAnimControl[ pSoldier->usAnimState ].dMovementChange, dAngle, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
pSoldier->MoveMerc( movementchange, dAngle, TRUE );
|
||||
}
|
||||
}
|
||||
// Check for direction change
|
||||
if ( gAnimControl[ pSoldier->usAnimState ].uiFlags & ANIM_TURNING )
|
||||
@@ -2007,8 +2005,8 @@ void HandleLocateToGuyAsHeWalks( SOLDIERTYPE *pSoldier )
|
||||
}
|
||||
}
|
||||
|
||||
#pragma optimize("gpt",on)
|
||||
__forceinline
|
||||
//#pragma optimize("gpt",on)
|
||||
// __forceinline
|
||||
BOOLEAN HandleGotoNewGridNo( SOLDIERTYPE *pSoldier, BOOLEAN *pfKeepMoving, BOOLEAN fInitialMove, UINT16 usAnimState )
|
||||
{
|
||||
INT16 sAPCost;
|
||||
|
||||
@@ -1410,6 +1410,12 @@ INT16 AStarPathfinder::CalcAP(int const terrainCost, UINT8 const direction)
|
||||
movementAPCost *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Flugente: dragging someone
|
||||
if ( pSoldier->IsDraggingSomeone( ) )
|
||||
{
|
||||
movementAPCost *= gItemSettings.fDragAPCostModifier;
|
||||
}
|
||||
|
||||
if (terrainCost == TRAVELCOST_FENCE)
|
||||
{
|
||||
switch( movementModeToUseForAPs )
|
||||
@@ -3641,6 +3647,12 @@ if(!GridNoOnVisibleWorldTile(iDestination))
|
||||
ubAPCost *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Flugente: dragging someone
|
||||
if ( s->IsDraggingSomeone( ) )
|
||||
{
|
||||
ubAPCost *= gItemSettings.fDragAPCostModifier;
|
||||
}
|
||||
|
||||
// SANDRO - moved backpack check to here
|
||||
// Moa: backpack penalty
|
||||
//if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( s ) != ITEM_NOT_FOUND )
|
||||
@@ -4717,6 +4729,12 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl
|
||||
{
|
||||
sMovementAPsCost *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Flugente: dragging someone
|
||||
if ( pSold->IsDraggingSomeone( ) )
|
||||
{
|
||||
sMovementAPsCost *= gItemSettings.fDragAPCostModifier;
|
||||
}
|
||||
|
||||
// Check for backpack
|
||||
//if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
@@ -4849,6 +4867,15 @@ INT32 PlotPath( SOLDIERTYPE *pSold, INT32 sDestGridNo, INT8 bCopyRoute, INT8 bPl
|
||||
sPointsRun *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Flugente: dragging someone
|
||||
if ( pSold->IsDraggingSomeone() )
|
||||
{
|
||||
sPointsWalk *= gItemSettings.fDragAPCostModifier;
|
||||
sPointsCrawl *= gItemSettings.fDragAPCostModifier;
|
||||
sPointsSwat *= gItemSettings.fDragAPCostModifier;
|
||||
sPointsRun *= gItemSettings.fDragAPCostModifier;
|
||||
}
|
||||
|
||||
// Check for backpack
|
||||
//if((UsingNewInventorySystem() == true) && FindBackpackOnSoldier( pSold ) != ITEM_NOT_FOUND )
|
||||
//{
|
||||
|
||||
+12
-5
@@ -216,7 +216,7 @@ INT16 BreathPointAdjustmentForCarriedWeight( SOLDIERTYPE * pSoldier )
|
||||
UINT32 uiCarriedPercent;
|
||||
UINT32 uiPercentCost;
|
||||
|
||||
uiCarriedPercent = CalculateCarriedWeight( pSoldier );
|
||||
uiCarriedPercent = CalculateCarriedWeight( pSoldier, TRUE );
|
||||
if (uiCarriedPercent < 101)
|
||||
{
|
||||
// normal BP costs
|
||||
@@ -476,9 +476,11 @@ INT16 ActionPointCost( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir, UINT16 u
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
sPoints *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Flugente: dragging someone
|
||||
if ( pSoldier->IsDraggingSomeone( ) )
|
||||
sPoints *= gItemSettings.fDragAPCostModifier;
|
||||
|
||||
// Flugente: scuba fins reduce movement cost in water, but increase cost on land
|
||||
if ( pSoldier->inv[LEGPOS].exists() && HasItemFlag( pSoldier->inv[LEGPOS].usItem, SCUBA_FINS ) )
|
||||
@@ -724,9 +726,11 @@ INT16 EstimateActionPointCost( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bDir,
|
||||
|
||||
// Flugente: riot shields lower movement speed
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
{
|
||||
sPoints *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
}
|
||||
|
||||
// Flugente: dragging someone
|
||||
if ( pSoldier->IsDraggingSomeone( ) )
|
||||
sPoints *= gItemSettings.fDragAPCostModifier;
|
||||
|
||||
// Check if doors if not player's merc (they have to open them manually)
|
||||
if ( sSwitchValue == TRAVELCOST_DOOR && pSoldier->bTeam != gbPlayerNum )
|
||||
@@ -4228,6 +4232,9 @@ INT16 GetAPsStartRun( SOLDIERTYPE *pSoldier )
|
||||
if ( pSoldier->IsRiotShieldEquipped( ) )
|
||||
val *= gItemSettings.fShieldMovementAPCostModifier;
|
||||
|
||||
if ( pSoldier->IsDraggingSomeone( ) )
|
||||
val *= gItemSettings.fDragAPCostModifier;
|
||||
|
||||
// Athletics trait
|
||||
if( HAS_SKILL_TRAIT( pSoldier, ATHLETICS_NT ) && gGameOptions.fNewTraitSystem )
|
||||
val = max( 1, (INT16)((val * (100 - gSkillTraitValues.ubATAPsMovementReduction) / 100) + 0.5) );
|
||||
|
||||
@@ -557,8 +557,19 @@ INT32 AddRottingCorpse( ROTTING_CORPSE_DEFINITION *pCorpseDef )
|
||||
AniParams.sDelay = (INT16)( 150 );
|
||||
AniParams.sStartFrame = 0;
|
||||
AniParams.uiFlags = ANITILE_CACHEDTILE | ANITILE_PAUSED | ANITILE_OPTIMIZEFORSLOWMOVING | ANITILE_ANIMATE_Z | ANITILE_ERASEITEMFROMSAVEBUFFFER | uiDirectionUseFlag;
|
||||
AniParams.sX = CenterX( pCorpse->def.sGridNo );
|
||||
AniParams.sY = CenterY( pCorpse->def.sGridNo );
|
||||
|
||||
// use the x,y coordinates provided in the definition when adding a corpse
|
||||
if (pCorpse->def.usFlags |= ROTTING_CORPSE_USE_XY_PROVIDED)
|
||||
{
|
||||
AniParams.sX = pCorpse->def.dXPos;
|
||||
AniParams.sY = pCorpse->def.dYPos;
|
||||
}
|
||||
else
|
||||
{
|
||||
AniParams.sX = CenterX(pCorpse->def.sGridNo);
|
||||
AniParams.sY = CenterY(pCorpse->def.sGridNo);
|
||||
}
|
||||
|
||||
AniParams.sZ = (INT16)pCorpse->def.sHeightAdjustment;
|
||||
AniParams.uiUserData3 = pCorpse->def.ubDirection;
|
||||
|
||||
@@ -2575,6 +2586,36 @@ UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo )
|
||||
return( ubHighestWarning );
|
||||
}
|
||||
|
||||
ROTTING_CORPSE* GetRottingCorpse( INT16 aNum )
|
||||
{
|
||||
if ( aNum < giNumRottingCorpse )
|
||||
return &(gRottingCorpse[aNum]);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::vector<INT16> GetCorpseIDsNearGridNo( INT32 sGridNo, INT8 bLevel, INT8 sRadius )
|
||||
{
|
||||
std::vector<INT16> idvec;
|
||||
|
||||
ROTTING_CORPSE* pCorpse;
|
||||
|
||||
for ( INT32 cnt = 0; cnt < giNumRottingCorpse; ++cnt )
|
||||
{
|
||||
pCorpse = &(gRottingCorpse[cnt]);
|
||||
|
||||
if ( pCorpse->fActivated && pCorpse->def.bLevel == bLevel )
|
||||
{
|
||||
if ( PythSpacesAway( sGridNo, pCorpse->def.sGridNo ) <= sRadius )
|
||||
{
|
||||
idvec.push_back(cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idvec;
|
||||
}
|
||||
|
||||
// Flugente Zombies: resurrect zombies
|
||||
void RaiseZombies( void )
|
||||
{
|
||||
|
||||
@@ -94,6 +94,8 @@ enum RottingCorpseDefines
|
||||
#define ROTTING_CORPSE_NO_VEST 0x00004000 // corpse has no vest (atm not visually)
|
||||
#define ROTTING_CORPSE_NO_PANTS 0x00008000 // corpse has no vest (atm not visually)
|
||||
|
||||
#define ROTTING_CORPSE_USE_XY_PROVIDED 0x00010000 // use the x,y coordinates provided in the definition when adding a corpse
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT8 ubType;
|
||||
@@ -220,6 +222,9 @@ INT32 GetGridNoOfCorpseGivenProfileID( UINT8 ubProfileID );
|
||||
void DecayRottingCorpseAIWarnings( void );
|
||||
UINT8 GetNearestRottingCorpseAIWarning( INT32 sGridNo );
|
||||
|
||||
ROTTING_CORPSE* GetRottingCorpse( INT16 aNum );
|
||||
std::vector<INT16> GetCorpseIDsNearGridNo( INT32 sGridNo, INT8 bLevel, INT8 sRadius );
|
||||
|
||||
// Flugente: Raise zombies
|
||||
void RaiseZombies( void );
|
||||
|
||||
|
||||
+92
-1
@@ -13,6 +13,8 @@
|
||||
#include "Queen Command.h"
|
||||
#include "strategicmap.h"
|
||||
#include "Map Screen Interface.h"
|
||||
#include "Rotting Corpses.h"
|
||||
|
||||
|
||||
extern void GetEquipmentTemplates( );
|
||||
|
||||
@@ -109,6 +111,13 @@ void Wrapper_Setup_SoldierSelection( UINT32 aVal) { gSoldierSelection.Setup(aVa
|
||||
void Wrapper_Cancel_SoldierSelection( UINT32 aVal ) { gSoldierSelection.Cancel(); }
|
||||
/////////////////////////////// Soldier Target Selection ////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////// Drag Selection ////////////////////////////////////////////
|
||||
DragSelection gDragSelection;
|
||||
|
||||
void Wrapper_Function_DragSelection( UINT32 aVal) { gDragSelection.Functions(aVal); }
|
||||
void Wrapper_Setup_DragSelection( UINT32 aVal ) { gDragSelection.Setup( aVal ); }
|
||||
void Wrapper_Cancel_DragSelection( UINT32 aVal ) { gDragSelection.Cancel( ); }
|
||||
/////////////////////////////// Drag Selection ////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////// Trait Selection ////////////////////////////////////////////
|
||||
void
|
||||
@@ -236,7 +245,10 @@ SkillSelection::Setup( UINT32 aVal )
|
||||
{
|
||||
swprintf( pStr, pTraitSkillsMenuStrings[uiCounter] );
|
||||
|
||||
pOption = new POPUP_OPTION(&std::wstring( pStr ), new popupCallbackFunction<void,UINT32>( &Wrapper_Function_SkillSelection, uiCounter ) );
|
||||
if ( uiCounter == SKILLS_DRAG )
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Setup_DragSelection, uiCounter ) );
|
||||
else
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_SkillSelection, uiCounter ) );
|
||||
|
||||
// if we cannot perform this skill, grey it out
|
||||
if ( !(pSoldier->CanUseSkill( uiCounter, TRUE, sTraitsMenuTargetGridNo )) )
|
||||
@@ -738,6 +750,85 @@ SoldierSelection::Functions( UINT32 aVal )
|
||||
}
|
||||
/////////////////////////////// Soldier Target Selection ////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////// Drag Selection ////////////////////////////////////////////
|
||||
void
|
||||
DragSelection::Setup( UINT32 aVal )
|
||||
{
|
||||
Destroy( );
|
||||
|
||||
SOLDIERTYPE * pSoldier = NULL;
|
||||
|
||||
GetSoldier( &pSoldier, gusSelectedSoldier );
|
||||
|
||||
if ( pSoldier == NULL )
|
||||
return;
|
||||
|
||||
if ( pSoldier->CanUseSkill( aVal ) )
|
||||
{
|
||||
usSkill = aVal;
|
||||
|
||||
SetupPopup( "DragSelection" );
|
||||
|
||||
POPUP_OPTION *pOption;
|
||||
|
||||
CHAR16 pStr[300];
|
||||
|
||||
// pretty simple: we find every soldier in a radius around the target position and add him to the list
|
||||
// loop through all soldiers around
|
||||
for ( UINT32 cnt = gTacticalStatus.Team[OUR_TEAM].bFirstID; cnt <= gTacticalStatus.Team[CIV_TEAM].bLastID; ++cnt )
|
||||
{
|
||||
if ( cnt != pSoldier->ubID && pSoldier->CanDragPerson(cnt) )
|
||||
{
|
||||
swprintf( pStr, L"%s", MercPtrs[cnt]->GetName( ) );
|
||||
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_DragSelection, cnt ) );
|
||||
|
||||
GetPopup( )->addOption( *pOption );
|
||||
}
|
||||
}
|
||||
|
||||
// corpses
|
||||
std::vector<INT16> corpseids = GetCorpseIDsNearGridNo( pSoldier->sGridNo, pSoldier->pathing.bLevel, 1 );
|
||||
|
||||
for ( std::vector<INT16>::iterator it = corpseids.begin(); it != corpseids.end(); ++it )
|
||||
{
|
||||
ROTTING_CORPSE* pCorpse = GetRottingCorpse( (*it) );
|
||||
|
||||
swprintf( pStr, pSkillMenuStrings[SKILLMENU_CORPSES], pCorpse->name );
|
||||
|
||||
// we have to use an offset of NOBODY in order to differentiate between person and corpse
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Function_DragSelection, (*it) + NOBODY ) );
|
||||
|
||||
GetPopup( )->addOption( *pOption );
|
||||
}
|
||||
|
||||
// cancel option
|
||||
swprintf( pStr, pSkillMenuStrings[SKILLMENU_CANCEL] );
|
||||
pOption = new POPUP_OPTION( &std::wstring( pStr ), new popupCallbackFunction<void, UINT32>( &Wrapper_Cancel_SoldierSelection, 0 ) );
|
||||
GetPopup( )->addOption( *pOption );
|
||||
}
|
||||
|
||||
// same y, different x
|
||||
SetPos( gSkillSelection.GetMaxPosX( ), usTraitMenuPosY );
|
||||
}
|
||||
|
||||
void
|
||||
DragSelection::Functions( UINT32 aVal )
|
||||
{
|
||||
SOLDIERTYPE * pSoldier = NULL;
|
||||
|
||||
GetSoldier( &pSoldier, gusSelectedSoldier );
|
||||
|
||||
if ( pSoldier )
|
||||
{
|
||||
pSoldier->UseSkill( usSkill, sTraitsMenuTargetGridNo, aVal );
|
||||
}
|
||||
|
||||
Cancel( );
|
||||
gSkillSelection.Cancel();
|
||||
gTraitSelection.Cancel( );
|
||||
}
|
||||
/////////////////////////////// Drag Selection ////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Flugente: traits menu popup box
|
||||
|
||||
@@ -155,6 +155,17 @@ private:
|
||||
UINT32 usSkill;
|
||||
};
|
||||
|
||||
class DragSelection : public SkillMenuItem
|
||||
{
|
||||
public:
|
||||
DragSelection( ) {}
|
||||
|
||||
void Setup( UINT32 aVal );
|
||||
void Functions( UINT32 aVal );
|
||||
|
||||
private:
|
||||
UINT32 usSkill;
|
||||
};
|
||||
|
||||
/**
|
||||
* Flugente: traits menu popup box
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
#include "MilitiaIndividual.h" // added by Flugente
|
||||
#include "Arms Dealer Init.h" // added by Flugente for armsDealerInfo[]
|
||||
#include "LuaInitNPCs.h" // added by Flugente
|
||||
#include "SaveLoadMap.h" // added by Flugente
|
||||
#endif
|
||||
|
||||
#include "ub_config.h"
|
||||
@@ -1027,6 +1028,8 @@ SOLDIERTYPE& SOLDIERTYPE::operator=(const OLDSOLDIERTYPE_101& src)
|
||||
this->bScopeMode = USE_BEST_SCOPE;
|
||||
|
||||
this->ubMilitiaAssists = 0;
|
||||
|
||||
this->CancelDrag();
|
||||
|
||||
this->bFoodLevel = 0;
|
||||
this->bDrinkLevel = 0;
|
||||
@@ -11193,12 +11196,10 @@ InternalpSoldier->GivingSoldierCancelServices(, FALSE );
|
||||
|
||||
void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckRange )
|
||||
{
|
||||
//INT16 dDegAngle;
|
||||
FLOAT dDeltaPos;
|
||||
FLOAT dXPos, dYPos;
|
||||
BOOLEAN fStop = FALSE;
|
||||
|
||||
|
||||
BOOLEAN fStop = FALSE;
|
||||
|
||||
//dDegAngle = (INT16)( dAngle * 180 / PI );
|
||||
//sprintf( gDebugStr, "Move Angle: %d", (int)dDegAngle );
|
||||
|
||||
@@ -11306,11 +11307,104 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: as we move a tile, we would now be too far away to drag someone.
|
||||
// So remember whether we were dragging (we have to set our position now, otherwise the person we drag woul soon occupy our gridno).
|
||||
BOOLEAN currentlydragging = this->IsDraggingSomeone();
|
||||
INT32 sOldGridNo = this->sGridNo;
|
||||
|
||||
// OK, set new position
|
||||
this->EVENT_InternalSetSoldierPosition( dXPos, dYPos, FALSE, FALSE, FALSE );
|
||||
|
||||
// Flugente: drag people
|
||||
if ( currentlydragging )
|
||||
{
|
||||
if ( this->usDragPersonID != NOBODY )
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[this->usDragPersonID];
|
||||
|
||||
// while it would be neat to take the opposite direction (which would make it look like we drag the other person by the legs),
|
||||
// this causes problems, as a prone person needs additional space for the legs. So just take the same direction
|
||||
//pSoldier->ubDirection = (this->ubDirection + 4 ) % NUM_WORLD_DIRECTIONS;
|
||||
pSoldier->ubDirection = this->ubDirection;
|
||||
|
||||
FLOAT dx = 0;
|
||||
FLOAT dy = 0;
|
||||
|
||||
INT32 gridnotouse = pSoldier->sGridNo;
|
||||
if ( sOldGridNo != this->sGridNo )
|
||||
{
|
||||
gridnotouse = sOldGridNo;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT16 this_base_x = 0;
|
||||
INT16 this_base_y = 0;
|
||||
ConvertMapPosToWorldTileCenter(this->sGridNo, &this_base_x, &this_base_y);
|
||||
|
||||
dx = this->dXPos - this_base_x;
|
||||
dy = this->dYPos - this_base_y;
|
||||
}
|
||||
|
||||
INT16 base_x = 0;
|
||||
INT16 base_y = 0;
|
||||
ConvertMapPosToWorldTileCenter( gridnotouse, &base_x, &base_y );
|
||||
|
||||
pSoldier->EVENT_InternalSetSoldierPosition( base_x + dx, base_y + dy, FALSE, FALSE, FALSE );
|
||||
}
|
||||
else if ( this->sDragCorpseID >= 0 )
|
||||
{
|
||||
ROTTING_CORPSE* pCorpse = GetRottingCorpse( this->sDragCorpseID );
|
||||
|
||||
if ( pCorpse )
|
||||
{
|
||||
// move corpse to new location. We have to actually delete and recreate the corpse, otherwise direction changes will only be visible after saving the game
|
||||
ROTTING_CORPSE_DEFINITION CorpseDef;
|
||||
|
||||
// Copy corpse definition...
|
||||
memcpy(&CorpseDef, &(pCorpse->def), sizeof(ROTTING_CORPSE_DEFINITION));
|
||||
|
||||
// Remove old one...
|
||||
RemoveCorpse(pCorpse->iID);
|
||||
|
||||
// drop blood at old location
|
||||
InternalDropBlood(pCorpse->def.sGridNo, this->pathing.bLevel, 0, 5, 1);
|
||||
|
||||
// adjust both gridno and x,y coordinates
|
||||
if (sOldGridNo != this->sGridNo)
|
||||
{
|
||||
CorpseDef.sGridNo = sOldGridNo;
|
||||
CorpseDef.dXPos = CenterX(CorpseDef.sGridNo);
|
||||
CorpseDef.dYPos = CenterY(CorpseDef.sGridNo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// move corpse a bit
|
||||
INT16 this_base_x = 0;
|
||||
INT16 this_base_y = 0;
|
||||
ConvertMapPosToWorldTileCenter(this->sGridNo, &this_base_x, &this_base_y);
|
||||
|
||||
FLOAT dx = this->dXPos - this_base_x;
|
||||
FLOAT dy = this->dYPos - this_base_y;
|
||||
|
||||
INT16 base_x = 0;
|
||||
INT16 base_y = 0;
|
||||
ConvertMapPosToWorldTileCenter(pCorpse->def.sGridNo, &base_x, &base_y);
|
||||
|
||||
CorpseDef.sGridNo = pCorpse->def.sGridNo;
|
||||
CorpseDef.dXPos = CenterX(CorpseDef.sGridNo) + dx;
|
||||
CorpseDef.dYPos = CenterY(CorpseDef.sGridNo) + dy;
|
||||
}
|
||||
|
||||
CorpseDef.usFlags |= ROTTING_CORPSE_USE_XY_PROVIDED;
|
||||
|
||||
CorpseDef.ubDirection = this->ubDirection;
|
||||
|
||||
this->sDragCorpseID = AddRottingCorpse(&CorpseDef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DebugMsg( TOPIC_JA2, DBG_LEVEL_3, String("X: %f Y: %f", dXPos, dYPos ) );
|
||||
|
||||
}
|
||||
|
||||
BOOLEAN GetDirectionChangeAmount( INT32 sGridNo, SOLDIERTYPE *pSoldier, UINT8 uiTurnAmount )
|
||||
@@ -17361,6 +17455,13 @@ BOOLEAN SOLDIERTYPE::CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck, INT32 sGridNo )
|
||||
canuse = TRUE;
|
||||
break;
|
||||
|
||||
case SKILLS_DRAG:
|
||||
|
||||
// TODO: a better check would be whether we can drag anything at the moment - CanDrag is more used for a specific person
|
||||
if ( CanDragInPrinciple() )
|
||||
canuse = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -17369,7 +17470,7 @@ BOOLEAN SOLDIERTYPE::CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck, INT32 sGridNo )
|
||||
}
|
||||
|
||||
// use a skill. For safety reasons, this calls CanUseSkill again
|
||||
BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID )
|
||||
BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID )
|
||||
{
|
||||
if ( !CanUseSkill( iSkill, TRUE, usMapPos ) )
|
||||
{
|
||||
@@ -17430,6 +17531,13 @@ BOOLEAN SOLDIERTYPE::UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID )
|
||||
}
|
||||
break;
|
||||
|
||||
case SKILLS_DRAG:
|
||||
if ( ID < NOBODY )
|
||||
SetDragOrderPerson( ID );
|
||||
else
|
||||
SetDragOrderCorpse( ID - NOBODY );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -17507,6 +17615,19 @@ STR16 SOLDIERTYPE::PrintSkillDesc( INT8 iSkill )
|
||||
|
||||
break;
|
||||
|
||||
case SKILLS_DRAG:
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_PRONEPERSONORCORPSE] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_CROUCH] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
swprintf( atStr, pTraitSkillsDenialStrings[TEXT_SKILL_DENIAL_FREEHANDS] );
|
||||
wcscat( skilldescarray, atStr );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -19353,6 +19474,156 @@ void SOLDIERTYPE::RiotShieldTakeDamage( INT32 sDamage )
|
||||
}
|
||||
}
|
||||
|
||||
// Flugente: drag people
|
||||
BOOLEAN SOLDIERTYPE::CanDragInPrinciple()
|
||||
{
|
||||
// only prone while crouched
|
||||
if ( gAnimControl[this->usAnimState].ubEndHeight != ANIM_CROUCH )
|
||||
return FALSE;
|
||||
|
||||
// not in water
|
||||
if ( TERRAIN_IS_HIGH_WATER( this->sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
// main hand must be free
|
||||
if ( this->inv[HANDPOS].exists( ) )
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::CanDragPerson( UINT8 usID )
|
||||
{
|
||||
if ( !CanDragInPrinciple() )
|
||||
return FALSE;
|
||||
|
||||
// check whether this guy exists etc.
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[usID];
|
||||
|
||||
if ( pSoldier && pSoldier->bActive && pSoldier->bInSector )
|
||||
{
|
||||
// must be on same level
|
||||
if ( pSoldier->pathing.bLevel != this->pathing.bLevel )
|
||||
return FALSE;
|
||||
|
||||
// only prone people can be dragged
|
||||
if ( gAnimControl[pSoldier->usAnimState].ubEndHeight != ANIM_PRONE )
|
||||
return FALSE;
|
||||
|
||||
// not in water
|
||||
if ( TERRAIN_IS_HIGH_WATER( pSoldier->sGridNo ) )
|
||||
return FALSE;
|
||||
|
||||
// don't drag nonsense around
|
||||
if ( pSoldier->ubBodyType >= COW || pSoldier->ubBodyType == QUEENMONSTER )
|
||||
return FALSE;
|
||||
|
||||
// must be near us
|
||||
if ( PythSpacesAway( pSoldier->sGridNo, this->sGridNo ) > 1 )
|
||||
return FALSE;
|
||||
|
||||
// we must be able to see the other guy even if if both would be prone. This is to stop the player from dragging someone through solid structures
|
||||
if ( !LocationToLocationLineOfSightTest(pSoldier->sGridNo, pSoldier->pathing.bLevel, this->sGridNo, this->pathing.bLevel, TRUE, CALC_FROM_ALL_DIRS, PRONE_LOS_POS, PRONE_LOS_POS))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::CanDragCorpse( UINT16 usCorpseNum )
|
||||
{
|
||||
if ( !CanDragInPrinciple( ) )
|
||||
return FALSE;
|
||||
|
||||
ROTTING_CORPSE* pCorpse = GetRottingCorpse( usCorpseNum );
|
||||
|
||||
if ( pCorpse )
|
||||
{
|
||||
// must be on same level
|
||||
if ( pCorpse->def.bLevel != this->pathing.bLevel )
|
||||
return FALSE;
|
||||
|
||||
// don't drag nonsense around
|
||||
if ( pCorpse->def.ubBodyType >= COW || pCorpse->def.ubBodyType == QUEENMONSTER )
|
||||
return FALSE;
|
||||
|
||||
// must be near us
|
||||
if ( PythSpacesAway( pCorpse->def.sGridNo, this->sGridNo ) > 2 )
|
||||
return FALSE;
|
||||
|
||||
// we must be able to see the other guy even if if both would be prone. This is to stop the player from dragging someone through solid structures
|
||||
if (!LocationToLocationLineOfSightTest(pCorpse->def.sGridNo, this->pathing.bLevel, this->sGridNo, this->pathing.bLevel, TRUE, CALC_FROM_ALL_DIRS, PRONE_LOS_POS, PRONE_LOS_POS))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOLEAN SOLDIERTYPE::IsDraggingSomeone( )
|
||||
{
|
||||
if ( this->sDragCorpseID >= 0 )
|
||||
{
|
||||
if ( this->CanDragCorpse(this->sDragCorpseID) )
|
||||
return TRUE;
|
||||
else
|
||||
CancelDrag();
|
||||
}
|
||||
else if ( this->usDragPersonID != NOBODY )
|
||||
{
|
||||
if ( this->CanDragPerson(this->usDragPersonID) )
|
||||
return TRUE;
|
||||
else
|
||||
CancelDrag();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::SetDragOrderPerson( UINT16 usID )
|
||||
{
|
||||
if ( CanDragPerson( usID ) )
|
||||
{
|
||||
CancelDrag();
|
||||
|
||||
this->usDragPersonID = usID;
|
||||
}
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::SetDragOrderCorpse( UINT32 usID )
|
||||
{
|
||||
if ( CanDragCorpse( usID ) )
|
||||
{
|
||||
CancelDrag();
|
||||
|
||||
this->sDragCorpseID = usID;
|
||||
}
|
||||
}
|
||||
|
||||
void SOLDIERTYPE::CancelDrag()
|
||||
{
|
||||
// if we are dragging a person, set them to the center of their gridno, otherwise their position might be off
|
||||
if (this->usDragPersonID != NOBODY)
|
||||
{
|
||||
SOLDIERTYPE* pSoldier = MercPtrs[this->usDragPersonID];
|
||||
|
||||
if ( pSoldier && !TileIsOutOfBounds(pSoldier->sGridNo) )
|
||||
{
|
||||
INT16 base_x = 0;
|
||||
INT16 base_y = 0;
|
||||
ConvertMapPosToWorldTileCenter(pSoldier->sGridNo, &base_x, &base_y);
|
||||
|
||||
pSoldier->EVENT_InternalSetSoldierPosition(base_x, base_y, FALSE, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
this->usDragPersonID = NOBODY;
|
||||
this->sDragCorpseID = -1;
|
||||
}
|
||||
|
||||
INT32 CheckBleeding( SOLDIERTYPE *pSoldier )
|
||||
{
|
||||
INT8 bBandaged; //,savedOurTurn;
|
||||
|
||||
@@ -416,6 +416,7 @@ enum
|
||||
|
||||
#define SOLDIER_COVERT_NOREDISGUISE 0x00001000 // this soldier does not want to be redisguised
|
||||
#define SOLDIER_TRAIT_FOCUS 0x00002000 // 'focus' skill is active
|
||||
#define SOLDIER_DRAG_CORPSE 0x00004000 // we are dragging a corpse, not a person
|
||||
|
||||
#define SOLDIER_INTERROGATE_ALL 0x000001F8 // all interrogation flags
|
||||
// ----------------------------------------------------------------
|
||||
@@ -590,7 +591,8 @@ enum{
|
||||
SKILLS_VARIOUS_FIRST,
|
||||
SKILLS_SPOTTER = SKILLS_VARIOUS_FIRST,
|
||||
SKILLS_FOCUS,
|
||||
SKILLS_VARIOUS_LAST = SKILLS_FOCUS,
|
||||
SKILLS_DRAG,
|
||||
SKILLS_VARIOUS_LAST = SKILLS_DRAG,
|
||||
|
||||
SKILLS_MAX,
|
||||
};
|
||||
@@ -1485,12 +1487,14 @@ public:
|
||||
// Flugente: this was the location of required variables required for the now removed poison feature. They can be used again
|
||||
UINT8 ubMilitiaAssists; // Flugente: stores militia assists
|
||||
INT8 sNonNPCTraderID; // Flugente: we can set up non-NPC soldiers to be merchants, we store their dealer id here (value > 0 means arms dealer entry x)
|
||||
INT8 bUnusedINT8_3;
|
||||
//INT8 bUnusedINT8_3;
|
||||
UINT8 usDragPersonID; // Flugente: id of person we are dragging
|
||||
|
||||
//INT16 bUnusedINT16_4;
|
||||
INT16 sDragCorpseID; // Flugente: id of corpse we are dragging
|
||||
|
||||
INT16 bUnusedINT16_4;
|
||||
INT16 bUnusedINT16_5;
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Flugente: new variables for extra stats
|
||||
INT16 bExtraStrength; // additional strength gained via power armor
|
||||
INT16 bExtraDexterity; // additional dexterity gained via drugs
|
||||
@@ -1866,7 +1870,7 @@ public:
|
||||
BOOLEAN CanUseSkill( INT8 iSkill, BOOLEAN fAPCheck = TRUE, INT32 sGridNo = -1 );
|
||||
|
||||
// use a skill. For safety reasons, this calls CanUseSkill again (it is possible to switch the soldier while the menu is open)
|
||||
BOOLEAN UseSkill( UINT8 iSkill, INT32 usMapPos, UINT8 ID );
|
||||
BOOLEAN UseSkill( UINT8 iSkill, INT32 usMapPos, UINT32 ID );
|
||||
|
||||
// is the AI allowed to use a skill? we have to check how much breath and life using this skill would cost, as otherwise the AI might commit suicide by casting
|
||||
BOOLEAN IsAIAllowedtoUseSkill( INT8 iSkill );
|
||||
@@ -1949,6 +1953,15 @@ public:
|
||||
BOOLEAN IsRiotShieldEquipped();
|
||||
void DestroyEquippedRiotShield();
|
||||
void RiotShieldTakeDamage(INT32 sDamage);
|
||||
|
||||
// Flugente: drag people
|
||||
BOOLEAN CanDragInPrinciple();
|
||||
BOOLEAN CanDragPerson( UINT8 usID );
|
||||
BOOLEAN CanDragCorpse( UINT16 usCorpseNum );
|
||||
BOOLEAN IsDraggingSomeone();
|
||||
void SetDragOrderPerson( UINT16 usID );
|
||||
void SetDragOrderCorpse( UINT32 usID );
|
||||
void CancelDrag();
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}; // SOLDIERTYPE;
|
||||
|
||||
Reference in New Issue
Block a user