From 49932ef90421561c59f5c7f8298ad8fcb87b7445 Mon Sep 17 00:00:00 2001 From: Flugente Date: Wed, 27 Mar 2013 22:06:26 +0000 Subject: [PATCH] - new feature: items can be applied to other persons - reduced cyanide drug effect to more reasonable values git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5962 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- GameSettings.cpp | 2 + Init.h | 2 + Tactical/Drugs And Alcohol.cpp | 15 +--- Tactical/Handle Items.cpp | 82 ++++++++++++++++++- Tactical/Handle UI.cpp | 40 ++++++++- Tactical/Handle UI.h | 1 + Tactical/Interface Cursors.cpp | 3 + Tactical/Interface Cursors.h | 3 + Tactical/Item Types.h | 1 + Tactical/Items.cpp | 24 ++++++ Tactical/Items.h | 3 + Tactical/Overhead.cpp | 5 ++ Tactical/Points.cpp | 11 +++ Tactical/Points.h | 1 + Tactical/Soldier Control.cpp | 144 +++++++++++++++++++++++++++++++++ Tactical/Soldier Control.h | 2 + Tactical/UI Cursors.cpp | 30 ++++++- Utils/Cursors.cpp | 22 ++++- Utils/Cursors.h | 5 ++ Utils/Text.h | 1 + Utils/_ChineseText.cpp | 1 + Utils/_DutchText.cpp | 1 + Utils/_EnglishText.cpp | 1 + Utils/_FrenchText.cpp | 1 + Utils/_GermanText.cpp | 1 + Utils/_ItalianText.cpp | 1 + Utils/_PolishText.cpp | 1 + Utils/_RussianText.cpp | 1 + Utils/_TaiwaneseText.cpp | 1 + 29 files changed, 387 insertions(+), 19 deletions(-) diff --git a/GameSettings.cpp b/GameSettings.cpp index 2db02c03a..b2ec5af12 100644 --- a/GameSettings.cpp +++ b/GameSettings.cpp @@ -2452,6 +2452,7 @@ void LoadGameAPBPConstants() APBPConstants[AP_CLEANINGKIT] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_CLEANINGKIT",80),80); APBPConstants[AP_DISGUISE] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_DISGUISE",80),80); APBPConstants[AP_HANDCUFF] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_HANDCUFF",50),50); + APBPConstants[AP_APPLYITEM] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_APPLYITEM",50),50); APBPConstants[AP_INVENTORY_ARM] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","AP_INVENTORY_ARM",50),50); APBPConstants[DEFAULT_APS] = DynamicAdjustAPConstants(iniReader.ReadInteger("APConstants","DEFAULT_APS",80),80); @@ -2510,6 +2511,7 @@ void LoadGameAPBPConstants() APBPConstants[BP_REMOVE_FORTIFICATION] = iniReader.ReadInteger("BPConstants","BP_REMOVE_FORTIFICATION", 400); APBPConstants[BP_FILL_SANDBAG] = iniReader.ReadInteger("BPConstants","BP_FILL_SANDBAG", 500); APBPConstants[BP_HANDCUFF] = iniReader.ReadInteger("BPConstants","BP_HANDCUFF", 100); + APBPConstants[BP_APPLYITEM] = iniReader.ReadInteger("BPConstants","BP_APPLYITEM", 50); APBPConstants[BP_INVENTORY_ARM] = iniReader.ReadInteger("BPConstants","BP_INVENTORY_ARM", 10); SetupMaxActionPointsAnimation(); diff --git a/Init.h b/Init.h index 633afa735..e9e56f14c 100644 --- a/Init.h +++ b/Init.h @@ -152,6 +152,7 @@ AP_EAT, AP_CLEANINGKIT, AP_DISGUISE, AP_HANDCUFF, +AP_APPLYITEM, AP_INVENTORY_ARM, DEFAULT_APS, @@ -209,6 +210,7 @@ BP_FORTIFICATION, BP_REMOVE_FORTIFICATION, BP_FILL_SANDBAG, BP_HANDCUFF, +BP_APPLYITEM, BP_INVENTORY_ARM, TOTAL_APBP_VALUES }; diff --git a/Tactical/Drugs And Alcohol.cpp b/Tactical/Drugs And Alcohol.cpp index e967bf978..3086c1ad0 100644 --- a/Tactical/Drugs And Alcohol.cpp +++ b/Tactical/Drugs And Alcohol.cpp @@ -415,20 +415,7 @@ void HandleEndTurnDrugAdjustments( SOLDIERTYPE *pSoldier ) // if we have a life damaging effect, deduct life points if ( pSoldier->drugs.bDrugEffect[ DRUG_TYPE_LIFEDAMAGE ] == 0 && pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_LIFEDAMAGE ] > 0 ) { - pSoldier->EVENT_SoldierGotHit( 0, 400, 0, pSoldier->ubDirection, 320, NOBODY , FIRE_WEAPON_NO_SPECIAL, pSoldier->bAimShotLocation, 0, -1 ); - - /*if ( pSoldier->stats.bLife > OKLIFE ) - { - INT8 lifepointdamage = pSoldier->drugs.bDrugSideEffect[ DRUG_TYPE_LIFEDAMAGE ]; - - INT8 applieddamage = pSoldier->stats.bLife; - - pSoldier->stats.bLife = max(OKLIFE - 8, pSoldier->stats.bLife - lifepointdamage); - - applieddamage -= pSoldier->stats.bLife; - - pSoldier->iHealableInjury += (applieddamage * 100); - }*/ + pSoldier->EVENT_SoldierGotHit( 0, 10, 0, pSoldier->ubDirection, 320, NOBODY , FIRE_WEAPON_NO_SPECIAL, pSoldier->bAimShotLocation, 0, -1 ); } // if we took an antidote, reduce poisoning diff --git a/Tactical/Handle Items.cpp b/Tactical/Handle Items.cpp index 3d4f86aee..86dc2487d 100644 --- a/Tactical/Handle Items.cpp +++ b/Tactical/Handle Items.cpp @@ -273,7 +273,7 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa return( ITEM_HANDLE_BROKEN ); } - if ( fFromUI && pSoldier->bTeam == gbPlayerNum && pTargetSoldier && (pTargetSoldier->bTeam == gbPlayerNum || pTargetSoldier->aiData.bNeutral) && pTargetSoldier->ubBodyType != CROW && Item[ usHandItem ].usItemClass != IC_MEDKIT ) + if ( fFromUI && pSoldier->bTeam == gbPlayerNum && pTargetSoldier && (pTargetSoldier->bTeam == gbPlayerNum || pTargetSoldier->aiData.bNeutral) && pTargetSoldier->ubBodyType != CROW && Item[ usHandItem ].usItemClass != IC_MEDKIT && !ItemCanBeAppliedToOthers(usHandItem) ) { if ( pSoldier->ubProfile != NO_PROFILE ) { @@ -1288,6 +1288,86 @@ INT32 HandleItem( SOLDIERTYPE *pSoldier, INT32 sGridNo, INT8 bLevel, UINT16 usHa else { pSoldier->EVENT_SoldierHandcuffPerson( sAdjustedGridNo, ubDirection ); + + UnSetUIBusy( pSoldier->ubID ); + } + + if ( fFromUI ) + { + guiPendingOverrideEvent = A_CHANGE_TO_MOVE; + } + + return( ITEM_HANDLE_OK ); + } + else + { + return( ITEM_HANDLE_NOAPS ); + } + } + + // Flugente: apply misc items to other soldiers + if ( ItemCanBeAppliedToOthers( usHandItem ) ) + { + // ATE: AI CANNOT GO THROUGH HERE! + INT32 usMapPos; + BOOLEAN fHadToUseCursorPos = FALSE; + + GetMouseMapPos( &usMapPos ); + + // See if we can get there to stab + sActionGridNo = FindAdjacentGridEx( pSoldier, sGridNo, &ubDirection, &sAdjustedGridNo, TRUE, FALSE ); + if ( sActionGridNo == -1 ) + { + // Try another location... + sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, &sAdjustedGridNo, TRUE, FALSE ); + + if ( sActionGridNo == -1 ) + { + return( ITEM_HANDLE_CANNOT_GETTO_LOCATION ); + } + } + + // Calculate AP costs... + sAPCost = GetAPsToApplyItem( pSoldier, sActionGridNo ); + sAPCost += PlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, FALSE, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints); + + if ( EnoughPoints( pSoldier, sAPCost, 0, fFromUI ) ) + { + // OK, set UI + SetUIBusy( pSoldier->ubID ); + + // CHECK IF WE ARE AT THIS GRIDNO NOW + if ( pSoldier->sGridNo != sActionGridNo ) + { + // SEND PENDING ACTION + pSoldier->aiData.ubPendingAction = MERC_APPLYITEM; + + if ( fHadToUseCursorPos ) + { + pSoldier->aiData.sPendingActionData2 = usMapPos; + } + else + { + if ( pTargetSoldier != NULL ) + { + pSoldier->aiData.sPendingActionData2 = pTargetSoldier->sGridNo; + } + else + { + pSoldier->aiData.sPendingActionData2 = sGridNo; + } + } + pSoldier->aiData.bPendingActionData3 = ubDirection; + pSoldier->aiData.ubPendingActionAnimCount = 0; + + // WALK UP TO DEST FIRST + pSoldier->EVENT_InternalGetNewSoldierPath( sActionGridNo, pSoldier->usUIMovementMode, FALSE, TRUE ); + } + else + { + pSoldier->EVENT_SoldierApplyItemToPerson( sAdjustedGridNo, ubDirection ); + + UnSetUIBusy( pSoldier->ubID ); } if ( fFromUI ) diff --git a/Tactical/Handle UI.cpp b/Tactical/Handle UI.cpp index 9249e7471..74a748d73 100644 --- a/Tactical/Handle UI.cpp +++ b/Tactical/Handle UI.cpp @@ -2745,7 +2745,12 @@ UINT32 UIHandleCAMercShoot( UI_EVENT *pUIEvent ) if ( pTSoldier != NULL ) { // If this is one of our own guys.....pop up requiester... - if ( ( pTSoldier->bTeam == gbPlayerNum || pTSoldier->bTeam == MILITIA_TEAM ) && Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass != IC_MEDKIT && !Item[pSoldier->inv[ HANDPOS ].usItem].gascan && gTacticalStatus.ubLastRequesterTargetID != pTSoldier->ubProfile && ( pTSoldier->ubID != pSoldier->ubID ) ) + if ( ( pTSoldier->bTeam == gbPlayerNum || pTSoldier->bTeam == MILITIA_TEAM ) + && Item[ pSoldier->inv[ HANDPOS ].usItem ].usItemClass != IC_MEDKIT + && !Item[pSoldier->inv[ HANDPOS ].usItem].gascan + && !ItemCanBeAppliedToOthers( pSoldier->inv[ HANDPOS ].usItem ) + && gTacticalStatus.ubLastRequesterTargetID != pTSoldier->ubProfile + && ( pTSoldier->ubID != pSoldier->ubID ) ) { CHAR16 zStr[200]; @@ -4159,6 +4164,24 @@ INT8 DrawUIMovementPath( SOLDIERTYPE *pSoldier, INT32 usMapPos, UINT32 uiFlags ) gsUIHandleShowMoveGridLocation = sActionGridNo; } } + else if ( uiFlags == MOVEUI_TARGET_APPLYITEM ) + { + sActionGridNo = FindAdjacentGridEx( pSoldier, usMapPos, &ubDirection, NULL, FALSE, TRUE ); + if ( sActionGridNo == -1 ) + { + sActionGridNo = usMapPos; + } + + sAPCost = GetAPsToApplyItem( pSoldier, sActionGridNo ); + + sAPCost += UIPlotPath( pSoldier, sActionGridNo, NO_COPYROUTE, fPlot, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints); + + if ( sActionGridNo != pSoldier->sGridNo ) + { + gfUIHandleShowMoveGrid = TRUE; + gsUIHandleShowMoveGridLocation = sActionGridNo; + } + } else if ( uiFlags == MOVEUI_TARGET_MERCS ) { INT32 sGotLocation = NOWHERE; @@ -4526,6 +4549,21 @@ BOOLEAN UIMouseOnValidAttackLocation( SOLDIERTYPE *pSoldier ) return( FALSE ); } + if ( ubItemCursor == APPLYITEMCURS ) + { + if ( ItemCanBeAppliedToOthers( (&(pSoldier->inv[HANDPOS]))->usItem ) ) + { + if ( gfUIFullTargetFound ) + { + usMapPos = MercPtrs[ gusUIFullTargetID ]->sGridNo; + + return( TRUE ); + } + } + + return( FALSE ); + } + if ( ubItemCursor == BOMBCURS ) { if ( usMapPos == pSoldier->sGridNo ) diff --git a/Tactical/Handle UI.h b/Tactical/Handle UI.h index fd9a04bbc..9ff3eafb8 100644 --- a/Tactical/Handle UI.h +++ b/Tactical/Handle UI.h @@ -31,6 +31,7 @@ #define MOVEUI_TARGET_REFUEL 12 #define MOVEUI_TARGET_FORTIFICATION 13 #define MOVEUI_TARGET_HANDCUFF 14 +#define MOVEUI_TARGET_APPLYITEM 15 #define MOVEUI_RETURN_ON_TARGET_MERC 1 diff --git a/Tactical/Interface Cursors.cpp b/Tactical/Interface Cursors.cpp index 6acce30ed..34e7800eb 100644 --- a/Tactical/Interface Cursors.cpp +++ b/Tactical/Interface Cursors.cpp @@ -218,6 +218,9 @@ UICursor gUICursors[ NUM_UI_CURSORS ] = HANDCUFF_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HANDCUFF, 0, HANDCUFF_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_HANDCUFF_RED, 0, + APPLYITEM_GREY_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_APPLYITEM, 0, + APPLYITEM_RED_UICURSOR, UICURSOR_FREEFLOWING, CURSOR_APPLYITEM_RED, 0, + }; diff --git a/Tactical/Interface Cursors.h b/Tactical/Interface Cursors.h index bf2e56f10..cd5108e79 100644 --- a/Tactical/Interface Cursors.h +++ b/Tactical/Interface Cursors.h @@ -192,6 +192,9 @@ typedef enum HANDCUFF_GREY_UICURSOR, HANDCUFF_RED_UICURSOR, + APPLYITEM_GREY_UICURSOR, + APPLYITEM_RED_UICURSOR, + NUM_UI_CURSORS } UICursorDefines; diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 07d15b6ce..83cd61466 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -175,6 +175,7 @@ typedef enum ATTACHMENT_SLOT{ #define REFUELCURS 23 #define FORTICURS 24 #define HANDCUFFCURS 25 +#define APPLYITEMCURS 26 #define CAMERARANGE 10 diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index fbd7a962b..e4e5eb2c0 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -14955,3 +14955,27 @@ BOOL RandomItemIsTaboo( UINT16 usRandomItem ) return FALSE; } + +// Flugente: can item be applied to other people? +BOOLEAN ItemCanBeAppliedToOthers( UINT16 usItem ) +{ + if ( Item[ usItem ].drugtype ) + return TRUE; + + if ( Item[ usItem ].gasmask ) + return TRUE; + + if ( Item[ usItem ].canteen ) + return TRUE; + + if ( Item[ usItem ].camouflagekit ) + return TRUE; + + if ( Item[ usItem ].clothestype ) + return TRUE; + + if ( Item[ usItem ].usItemClass == IC_BOMB ) + return TRUE; + + return FALSE; +} diff --git a/Tactical/Items.h b/Tactical/Items.h index a7377fd38..56d1e3915 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -507,6 +507,9 @@ BOOLEAN GetFirstClothesItemWithSpecificData( UINT16* pusItem, PaletteRepID aPalV // Flugente: function to determine what item a random item spawns BOOLEAN GetItemFromRandomItem( UINT16 usRandomItem, UINT16* pusNewItem ); +// Flugente: can item be applied to other people? +BOOLEAN ItemCanBeAppliedToOthers( UINT16 usItem ); + #endif diff --git a/Tactical/Overhead.cpp b/Tactical/Overhead.cpp index 6c4037bfa..8d3c9a968 100644 --- a/Tactical/Overhead.cpp +++ b/Tactical/Overhead.cpp @@ -1665,6 +1665,11 @@ BOOLEAN ExecuteOverhead( ) pSoldier->EVENT_SoldierHandcuffPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; } + else if ( pSoldier->aiData.ubPendingAction == MERC_APPLYITEM ) + { + pSoldier->EVENT_SoldierApplyItemToPerson( pSoldier->aiData.sPendingActionData2, pSoldier->aiData.bPendingActionData3 ); + pSoldier->aiData.ubPendingAction = NO_PENDING_ACTION; + } else if ( pSoldier->aiData.ubPendingAction == MERC_GIVEITEM ) { pSoldier->EVENT_SoldierBeginGiveItem( ); diff --git a/Tactical/Points.cpp b/Tactical/Points.cpp index 6d8916daf..3f187a433 100644 --- a/Tactical/Points.cpp +++ b/Tactical/Points.cpp @@ -3713,6 +3713,17 @@ INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos ) return sAPCost; } +INT16 GetAPsToApplyItem( SOLDIERTYPE *pSoldier, INT32 usMapPos ) +{ + INT16 sAPCost = 0; + + sAPCost = PlotPath( pSoldier, usMapPos, NO_COPYROUTE, NO_PLOT, TEMPORARY, (UINT16)pSoldier->usUIMovementMode, NOT_STEALTH, FORWARD, pSoldier->bActionPoints ); + + sAPCost += APBPConstants[AP_APPLYITEM]; + + return sAPCost; +} + INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier ) { // -25% APs needed to for MA traits diff --git a/Tactical/Points.h b/Tactical/Points.h index 6e18cd377..2d231b3d6 100644 --- a/Tactical/Points.h +++ b/Tactical/Points.h @@ -357,6 +357,7 @@ INT16 GetAPsToUseCan( SOLDIERTYPE *pSoldier, INT32 usMapPos ); INT16 GetBPsTouseJar( SOLDIERTYPE *pSoldier ); INT16 GetAPsToHandcuff( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente +INT16 GetAPsToApplyItem( SOLDIERTYPE *pSoldier, INT32 usMapPos ); // added by Flugente INT16 GetAPsToJumpOver( SOLDIERTYPE *pSoldier ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index c96a0d7cb..465286818 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -16944,6 +16944,150 @@ void SOLDIERTYPE::EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection } } +void SOLDIERTYPE::EVENT_SoldierApplyItemToPerson( INT32 sGridNo, UINT8 ubDirection ) +{ + UINT8 ubPerson = WhoIsThere2( sGridNo, this->pathing.bLevel ); + + if ( ubPerson != NOBODY ) + { + // we found someone + SOLDIERTYPE* pSoldier = MercPtrs[ ubPerson ]; + + OBJECTTYPE* pObj = &(this->inv[ HANDPOS ]); + + if ( pSoldier && pObj->exists() ) + { + UINT16 usItem = pObj->usItem; + + if ( ItemCanBeAppliedToOthers( usItem ) ) + { + BOOLEAN success = TRUE; + + // if the other guy is not on our side, and he is concious, he resists + if ( this->bSide != pSoldier->bSide && !pSoldier->bCollapsed ) + { + // wether we are sucessful depends on dexterity, and his alert status (he gets a malus on green state) + UINT32 attackervalue = 30 + 4 * EffectiveExpLevel( this ) + EffectiveDexterity( this, FALSE ) + 20 * HAS_SKILL_TRAIT(this, STEALTHY_NT); + UINT32 defendervalue = 100 + 3 * EffectiveExpLevel( pSoldier ) + 100 * (pSoldier->aiData.bAlertStatus - 1); + + // we are penalized for the weight of the item + UINT16 weight = pObj->GetWeightOfObjectInStack(0); + attackervalue = attackervalue / weight; + + if ( Random(attackervalue) > Random(defendervalue) ) + success = TRUE; + else + { + success = FALSE; + + // if we are disguised, there is a chance that he'll uncover us + if ( this->bSoldierFlagMask & (SOLDIER_COVERT_CIV|SOLDIER_COVERT_SOLDIER) ) + { + this->LooseDisguise(); + this->Strip(); + + // alert the soldier + pSoldier->aiData.bAlertStatus = min(pSoldier->aiData.bAlertStatus, STATUS_RED); + + ProcessImplicationsOfPCAttack( this, &pSoldier, REASON_NORMAL_ATTACK ); + + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_APPLYITEM_STEAL_FAIL], this->name, pSoldier->name ); + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_UNCOVERED], pSoldier->name, this->name ); + } + } + } + + if ( success ) + { + if ( !gGameOptions.fFoodSystem && Item[ usItem ].canteen ) + { + BOOLEAN tmp = FALSE; + success = ApplyCanteen( pSoldier, pObj, &tmp ); + } + else if ( Item[ usItem ].drugtype || Item[ usItem ].canteen ) + { + // applying drugs also handles food items + success = ApplyDrugs( pSoldier, pObj ); + } + else if ( Item[ usItem ].camouflagekit ) + { + BOOLEAN tmp = FALSE; + success = ApplyCammo( pSoldier, pObj, &tmp ); + + if ( success ) + { + // WANNE: We should only delete the face, if there was a camo we applied. + // This should fix the bug and crashes with missing faces + if (gGameExternalOptions.fShowCamouflageFaces == TRUE ) + { + // Flugente: refresh face regardless of result of SetCamoFace(), otherwise applying a rag will not clean the picture + SetCamoFace( pSoldier ); + DeleteSoldierFace( pSoldier );// remove face + pSoldier->iFaceIndex = InitSoldierFace( pSoldier );// create new face + } + + // Dirty + fInterfacePanelDirty = DIRTYLEVEL2; + } + } + else if ( Item[ usItem ].gasmask ) + { + // put this item into a (at best empty) faceslot if no gasmask is been worn + INT8 bSlot = FindGasMask( pSoldier ); + if ( bSlot == NO_SLOT || (bSlot != HEAD1POS && bSlot != HEAD2POS ) ) + { + if ( !(pSoldier->inv[HEAD1POS]).exists() ) + { + success = PlaceObject( pSoldier, HEAD1POS, pObj ); + } + else if ( !(pSoldier->inv[HEAD2POS]).exists() ) + { + success = PlaceObject( pSoldier, HEAD2POS, pObj ); + } + else + { + // no gasmask is worn, and both faceslots are occupied - remove the item in slot 2 and put the gasmask there + AddItemToPool( pSoldier->sGridNo, &(pSoldier->inv[HEAD2POS]), 1, pSoldier->pathing.bLevel, 0, -1 ); + + success = PlaceObject( pSoldier, HEAD2POS, pObj ); + } + } + } + else if ( Item[ usItem ].clothestype ) + { + ApplyClothes( pSoldier, pObj ); + + // Dirty + fInterfacePanelDirty = DIRTYLEVEL2; + } + else if ( Item[ usItem ].usItemClass == IC_BOMB ) + { + success = AutoPlaceObjectAnywhere( pSoldier, pObj, FALSE ); + } + + this->DoMercBattleSound( BATTLE_SOUND_COOL1 ); + } + + DeductPoints( this, GetAPsToApplyItem( this, sGridNo ), APBPConstants[BP_APPLYITEM], AFTERACTION_INTERRUPT ); + + if ( !success ) + ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, L"%s could not apply %s to %s.", this->name, Item[usItem].szLongItemName, pSoldier->name ); + } + else + { + DeductPoints( this, GetAPsToApplyItem( this, sGridNo ), APBPConstants[BP_APPLYITEM], AFTERACTION_INTERRUPT ); + + // curses! + this->DoMercBattleSound( BATTLE_SOUND_CURSE1 ); + } + + return; + } + } + + // Say NOTHING quote... + this->DoMercBattleSound( BATTLE_SOUND_NOTHING ); +} void SOLDIERTYPE::EVENT_SoldierBeginReloadRobot( INT32 sGridNo, UINT8 ubDirection, UINT8 ubMercSlot ) { diff --git a/Tactical/Soldier Control.h b/Tactical/Soldier Control.h index d99f17476..4d8b05aa2 100644 --- a/Tactical/Soldier Control.h +++ b/Tactical/Soldier Control.h @@ -224,6 +224,7 @@ enum MERC_FUEL_VEHICLE, MERC_BUILD_FORTIFICATION, MERC_HANDCUFF_PERSON, + MERC_APPLYITEM, }; // ENUMERATIONS FOR THROW ACTIONS @@ -1342,6 +1343,7 @@ public: void EVENT_SoldierBuildStructure( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente void EVENT_SoldierHandcuffPerson( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente + void EVENT_SoldierApplyItemToPerson( INT32 sGridNo, UINT8 ubDirection ); // added by Flugente BOOLEAN EVENT_InternalGetNewSoldierPath( INT32 sDestGridNo, UINT16 usMovementAnim, BOOLEAN fFromUI, BOOLEAN fForceRestart ); void EVENT_InternalSetSoldierDestination( UINT16 usNewDirection, BOOLEAN fFromMove, UINT16 usAnimState ); diff --git a/Tactical/UI Cursors.cpp b/Tactical/UI Cursors.cpp index 8abd5b40d..85c2307c5 100644 --- a/Tactical/UI Cursors.cpp +++ b/Tactical/UI Cursors.cpp @@ -54,7 +54,8 @@ UINT8 HandleBombCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, BOOLEAN fActivated UINT8 HandleJarCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); UINT8 HandleTinCanCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); UINT8 HandleFortificationCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente -UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente +UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente +UINT8 HandleApplyItemCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ); //added by Flugente extern BOOLEAN HandleCheckForBadChangeToGetThrough( SOLDIERTYPE *pSoldier, SOLDIERTYPE *pTargetSoldier, INT32 sTargetGridNo , INT8 bLevel ); @@ -310,6 +311,11 @@ UINT8 GetProperItemCursor( UINT8 ubSoldierID, UINT16 ubItemIndex, INT32 usMapPos ubCursorID = HandleHandcuffCursor( pSoldier, sTargetGridNo, uiCursorFlags ); break; + case APPLYITEMCURS: + + ubCursorID = HandleApplyItemCursor( pSoldier, sTargetGridNo, uiCursorFlags ); + break; + case INVALIDCURS: ubCursorID = INVALID_ACTION_UICURSOR; @@ -2235,6 +2241,24 @@ UINT8 HandleHandcuffCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCurso return( HANDCUFF_RED_UICURSOR ); } +UINT8 HandleApplyItemCursor( SOLDIERTYPE *pSoldier, INT32 sGridNo, UINT32 uiCursorFlags ) +{ + // DRAW PATH TO GUY + HandleUIMovementCursor( pSoldier, uiCursorFlags, sGridNo, MOVEUI_TARGET_APPLYITEM ); + + if ( ItemCanBeAppliedToOthers( (&(pSoldier->inv[HANDPOS]))->usItem ) ) + { + // is there a person here? + UINT8 usSoldierIndex = WhoIsThere2( sGridNo, pSoldier->pathing.bLevel ); + if ( usSoldierIndex != NOBODY ) + { + return( APPLYITEM_GREY_UICURSOR ); + } + } + + return( APPLYITEM_RED_UICURSOR ); +} + void HandleEndConfirmCursor( SOLDIERTYPE *pSoldier ) { UINT16 usInHand; @@ -2714,6 +2738,10 @@ UINT8 GetActionModeCursor( SOLDIERTYPE *pSoldier ) if ( gGameExternalOptions.fAllowPrisonerSystem && HasItemFlag(usInHand, HANDCUFFS) ) ubCursor = HANDCUFFCURS; + // Flugente: apply misc items to other soldiers + if ( ItemCanBeAppliedToOthers( usInHand ) ) + ubCursor = APPLYITEMCURS; + // Now check our terrain to see if we cannot do the action now... if ( WaterTooDeepForAttacks( pSoldier->sGridNo) ) { diff --git a/Utils/Cursors.cpp b/Utils/Cursors.cpp index eb97dbb22..62566b5d0 100644 --- a/Utils/Cursors.cpp +++ b/Utils/Cursors.cpp @@ -119,12 +119,15 @@ CursorFileData CursorFileDatabase[] = { "CURSORS\\bullseye.sti" , FALSE, 0, 0, 0, NULL }, { "CURSORS\\deadleap.sti" , FALSE, 0, 0, 0, NULL }, - { "CURSORS\\hammer.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: fortification stuff + { "CURSORS\\hammer.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: fortification { "CURSORS\\hammer_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, - { "CURSORS\\handcuffs.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: handcuffs stuff + { "CURSORS\\handcuffs.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: handcuffs { "CURSORS\\handcuffs_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, + { "CURSORS\\apply_r.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // Flugente: apply items - still needs animation + { "CURSORS\\apply.sti" , FALSE, 0, ANIMATED_CURSOR, 3, NULL }, // yes, the red one is the 'valid' one - just like for taking items + { "CURSORS\\can_01.sti" , FALSE, 0, 0, 0, NULL }, { "CURSORS\\can_02.sti" , FALSE, 0, 0, 0, NULL }, { "CURSORS\\cur_tagr_ncth.sti" , FALSE, 0, ANIMATED_CURSOR, 7, NULL }, @@ -1215,6 +1218,21 @@ CursorData CursorDatabase[] = 0, 0, 0, 0, 0, 2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 }, + // Flugente: apply item + { C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR, + C_APPLYITEM , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 }, + + { C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR, + C_APPLYITEM_RED , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 2, CENTER_CURSOR, CENTER_CURSOR, 0, 0 , 0, 0 }, + { C_TRINGS, 6, 0, HIDE_SUBCURSOR, HIDE_SUBCURSOR, C_FUEL , 0, 0, CENTER_SUBCURSOR, CENTER_SUBCURSOR, 0, 0, 0, 0, 0, diff --git a/Utils/Cursors.h b/Utils/Cursors.h index a34789763..b0bbaf0a0 100644 --- a/Utils/Cursors.h +++ b/Utils/Cursors.h @@ -159,6 +159,9 @@ typedef enum CURSOR_HANDCUFF, CURSOR_HANDCUFF_RED, + CURSOR_APPLYITEM, + CURSOR_APPLYITEM_RED, + CURSOR_FUEL, CURSOR_FUEL_RED, @@ -236,6 +239,8 @@ typedef enum C_FORTIFICATION_RED, C_HANDCUFFS, C_HANDCUFFS_RED, + C_APPLYITEM, + C_APPLYITEM_RED, C_FUEL, C_FUEL_RED, C_ACTIONMODERED_NCTH, diff --git a/Utils/Text.h b/Utils/Text.h index 861d2a2ae..2aef917e7 100644 --- a/Utils/Text.h +++ b/Utils/Text.h @@ -689,6 +689,7 @@ enum STR_COVERT_TEST_OK, STR_COVERT_TEST_FAIL, STR_COVERT_STEAL_FAIL, + STR_COVERT_APPLYITEM_STEAL_FAIL, TEXT_NUM_COVERT_STR }; diff --git a/Utils/_ChineseText.cpp b/Utils/_ChineseText.cpp index 8013e4ebc..fa5d821aa 100644 --- a/Utils/_ChineseText.cpp +++ b/Utils/_ChineseText.cpp @@ -7493,6 +7493,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_DutchText.cpp b/Utils/_DutchText.cpp index 6e1527639..869bc39cb 100644 --- a/Utils/_DutchText.cpp +++ b/Utils/_DutchText.cpp @@ -7490,6 +7490,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_EnglishText.cpp b/Utils/_EnglishText.cpp index 96b1990a7..4ec9154d1 100644 --- a/Utils/_EnglishText.cpp +++ b/Utils/_EnglishText.cpp @@ -7479,6 +7479,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_FrenchText.cpp b/Utils/_FrenchText.cpp index 47f7c99f8..8a53640b6 100644 --- a/Utils/_FrenchText.cpp +++ b/Utils/_FrenchText.cpp @@ -7474,6 +7474,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_GermanText.cpp b/Utils/_GermanText.cpp index 7ffd8fdb2..b79d26608 100644 --- a/Utils/_GermanText.cpp +++ b/Utils/_GermanText.cpp @@ -7302,6 +7302,7 @@ STR16 szCovertTextStr[]= L"%s's Verkleidung sollte überzeugen", L"%s's Verkleidung wird auffliegen!", L"%s wurde beim Stehlen erwischt!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_ItalianText.cpp b/Utils/_ItalianText.cpp index 37387a380..59cdddeb7 100644 --- a/Utils/_ItalianText.cpp +++ b/Utils/_ItalianText.cpp @@ -7476,6 +7476,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_PolishText.cpp b/Utils/_PolishText.cpp index 75c7f356a..a71350cfb 100644 --- a/Utils/_PolishText.cpp +++ b/Utils/_PolishText.cpp @@ -7497,6 +7497,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_RussianText.cpp b/Utils/_RussianText.cpp index 8fca5041f..c3524d492 100644 --- a/Utils/_RussianText.cpp +++ b/Utils/_RussianText.cpp @@ -7478,6 +7478,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]= diff --git a/Utils/_TaiwaneseText.cpp b/Utils/_TaiwaneseText.cpp index 159015b26..47210daff 100644 --- a/Utils/_TaiwaneseText.cpp +++ b/Utils/_TaiwaneseText.cpp @@ -7494,6 +7494,7 @@ STR16 szCovertTextStr[]= L"%s's disguise seems to be ok...", L"%s's disguise will not hold.", L"%s was caught stealing!", + L"%s tried to manipulate %s's inventory." }; STR16 szCorpseTextStr[]=