diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index 51519485..d20000b5 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -10332,7 +10332,7 @@ INT16 GetBaseScopeAimBonus( OBJECTTYPE * pObj, INT32 iRange ) } // Madd: check equipment for aim bonus (penalties) -INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 ubAimTime ) +INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 sAimTime ) { INT16 bonus=0; @@ -10340,10 +10340,10 @@ INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 ubAimTime ) { OBJECTTYPE* pObj = &pSoldier->inv[j]; if (pObj->exists() == true) { - bonus += GetItemAimBonus( &Item[pSoldier->inv[j].usItem], iRange, ubAimTime ); + bonus += GetItemAimBonus( &Item[pSoldier->inv[j].usItem], iRange, sAimTime ); for (attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); ++iter) { if(iter->exists()){ - bonus += GetItemAimBonus(&Item[iter->usItem],iRange,ubAimTime); + bonus += GetItemAimBonus(&Item[iter->usItem],iRange, sAimTime); } } } diff --git a/Tactical/Items.h b/Tactical/Items.h index b1cf30c1..ebb3d4cd 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -272,7 +272,7 @@ INT16 GetBestLaserRange( OBJECTTYPE * pObj ); INT16 GetBipodBonus( OBJECTTYPE * pObj ); INT16 GetBurstToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE ); INT16 GetAutoToHitBonus( OBJECTTYPE * pObj, BOOLEAN fProneStance = FALSE ); -INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 ubAimTime); +INT16 GetGearAimBonus( SOLDIERTYPE * pSoldier, INT32 iRange, INT16 sAimTime); INT16 GetGearToHitBonus( SOLDIERTYPE * pSoldier ); INT16 GetMinRangeForAimBonus( SOLDIERTYPE* pSoldier, OBJECTTYPE * pObj ); diff --git a/Tactical/Soldier Control.cpp b/Tactical/Soldier Control.cpp index abbc69e1..740e6915 100644 --- a/Tactical/Soldier Control.cpp +++ b/Tactical/Soldier Control.cpp @@ -11837,7 +11837,7 @@ void SOLDIERTYPE::MoveMerc( FLOAT dMovementChange, FLOAT dAngle, BOOLEAN fCheckR if ( BuildStructDrag( sOldGridNo, gsInterfaceLevel, arusTileType, arusStructureNumber, this->ubID ) ) { // remove - RemoveStructDrag( this->sDragGridNo, gsInterfaceLevel, arusTileType ); + RemoveStructDrag( this->sDragGridNo, (INT8)gsInterfaceLevel, arusTileType ); // also move doors, this includes moving locks and traps DOOR* pDoor = FindDoorInfoAtGridNo( this->sDragGridNo ); @@ -16095,14 +16095,14 @@ BOOLEAN SOLDIERTYPE::SeemsLegit( UINT8 ubObserverID ) } } - // if we are trying to dress like a civilian, but aren't sucessful: not covert + // if we are trying to dress like a civilian, but aren't successful: not covert if ( this->usSoldierFlagMask & SOLDIER_COVERT_CIV && !(this->LooksLikeACivilian( )) ) { ScreenMsg( FONT_MCOLOR_LTYELLOW, MSG_INTERFACE, szCovertTextStr[STR_COVERT_NO_CIV], this->GetName( ) ); return FALSE; } - // if we are trying to dress like a soldier, but aren't sucessful: not covert + // if we are trying to dress like a soldier, but aren't successful: not covert if ( this->usSoldierFlagMask & SOLDIER_COVERT_SOLDIER && !(this->LooksLikeASoldier( )) ) { return FALSE; @@ -20556,7 +20556,8 @@ BOOLEAN SOLDIERTYPE::CanDragPerson( UINT16 usID ) 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)) + //if ( !LocationToLocationLineOfSightTest(pSoldier->sGridNo, pSoldier->pathing.bLevel, this->sGridNo, this->pathing.bLevel, TRUE, CALC_FROM_ALL_DIRS, PRONE_LOS_POS, PRONE_LOS_POS)) + if (gubWorldMovementCosts[pSoldier->sGridNo][AIDirection(this->sGridNo, pSoldier->sGridNo)][this->pathing.bLevel] >= TRAVELCOST_BLOCKED) return FALSE; return TRUE; @@ -20587,7 +20588,8 @@ BOOLEAN SOLDIERTYPE::CanDragCorpse( UINT16 usCorpseNum ) 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)) + //if (!LocationToLocationLineOfSightTest(pCorpse->def.sGridNo, this->pathing.bLevel, this->sGridNo, this->pathing.bLevel, TRUE, CALC_FROM_ALL_DIRS, PRONE_LOS_POS, PRONE_LOS_POS)) + if (this->sGridNo != pCorpse->def.sGridNo && gubWorldMovementCosts[pCorpse->def.sGridNo][AIDirection(this->sGridNo, pCorpse->def.sGridNo)][this->pathing.bLevel] >= TRAVELCOST_BLOCKED) return FALSE; return TRUE; diff --git a/Tactical/Turn Based Input.cpp b/Tactical/Turn Based Input.cpp index 325433a2..3e212332 100644 --- a/Tactical/Turn Based Input.cpp +++ b/Tactical/Turn Based Input.cpp @@ -2070,6 +2070,13 @@ void GetKeyboardInput( UINT32 *puiNewEvent ) // If soldier is not stationary, stop MercPtrs[ gusSelectedSoldier ]->StopSoldier( ); *puiNewEvent = A_CHANGE_TO_MOVE; + + // sevenfm: also stop dragging + if (MercPtrs[gusSelectedSoldier]->IsDraggingSomeone(false)) + { + MercPtrs[gusSelectedSoldier]->CancelDrag(); + DirtyMercPanelInterface(MercPtrs[gusSelectedSoldier], DIRTYLEVEL2); + } } // ATE: OK, stop any mercs who are moving by selection method.... StopRubberBandedMercFromMoving( ); diff --git a/Tactical/opplist.cpp b/Tactical/opplist.cpp index ce761bca..41976eb8 100644 --- a/Tactical/opplist.cpp +++ b/Tactical/opplist.cpp @@ -2633,14 +2633,16 @@ void ManSeesMan(SOLDIERTYPE *pSoldier, SOLDIERTYPE *pOpponent, INT32 sOppGridNo, // if the looker hasn't seen this opponent at all earlier this turn, OR // if the opponent is not where the looker last thought him to be - if ((pSoldier->aiData.bOppList[pOpponent->ubID] != SEEN_THIS_TURN) || (gsLastKnownOppLoc[pSoldier->ubID][pOpponent->ubID] != sOppGridNo)) + // sevenfm: only call SetNewSituation if location is different to reduce frequency of AI re-evaluation + //if ((pSoldier->aiData.bOppList[pOpponent->ubID] != SEEN_THIS_TURN) || (gsLastKnownOppLoc[pSoldier->ubID][pOpponent->ubID] != sOppGridNo)) + if (KnownLocation(pSoldier, pOpponent->ubID) != sOppGridNo || KnownLevel(pSoldier, pOpponent->ubID) != bOppLevel) { SetNewSituation( pSoldier ); // force the looker to re-evaluate // anv: simulate informing buddies about detected enemy's position // sevenfm: check that he is really new - if( gbPublicOpplist[pSoldier->bTeam][pOpponent->ubID] != SEEN_CURRENTLY && gbPublicOpplist[pSoldier->bTeam][pOpponent->ubID] != SEEN_THIS_TURN ) + //if( gbPublicOpplist[pSoldier->bTeam][pOpponent->ubID] != SEEN_CURRENTLY && gbPublicOpplist[pSoldier->bTeam][pOpponent->ubID] != SEEN_THIS_TURN ) + if (gbSeenOpponents[pSoldier->ubID][pOpponent->ubID] < 1 && gbPublicOpplist[pSoldier->bTeam][pOpponent->ubID] < SEEN_CURRENTLY) PossiblyStartEnemyTaunt( pSoldier, TAUNT_INFORM_ABOUT, pOpponent->ubID ); - } else { diff --git a/TacticalAI/AIMain.cpp b/TacticalAI/AIMain.cpp index 81a9c564..2266f255 100644 --- a/TacticalAI/AIMain.cpp +++ b/TacticalAI/AIMain.cpp @@ -1793,6 +1793,14 @@ void AIDecideRadioAnimation( SOLDIERTYPE *pSoldier ) return; } + // sevenfm: only allow radio animation on initial red alert + if (gTacticalStatus.Team[pSoldier->bTeam].bAwareOfOpposition || SectorJammed()) + { + // don't play animation + ActionDone(pSoldier); + return; + } + switch( gAnimControl[ pSoldier->usAnimState ].ubEndHeight ) { case ANIM_STAND: @@ -2555,7 +2563,8 @@ INT8 ExecuteAction(SOLDIERTYPE *pSoldier) if(bSlot != NO_SLOT) { ReloadGun( pSoldier, &(pSoldier->inv[pSoldier->aiData.usActionData]), &(pSoldier->inv[bSlot]) ); - PossiblyStartEnemyTaunt( pSoldier, TAUNT_RELOAD ); + if (Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) || GetMagSize(&(pSoldier->inv[pSoldier->aiData.usActionData])) > 4) + PossiblyStartEnemyTaunt( pSoldier, TAUNT_RELOAD ); ActionDone( pSoldier ); } break; diff --git a/TacticalAI/AIUtils.cpp b/TacticalAI/AIUtils.cpp index 7d0222c6..56849ea0 100644 --- a/TacticalAI/AIUtils.cpp +++ b/TacticalAI/AIUtils.cpp @@ -4882,13 +4882,16 @@ UINT8 SpotDangerLevel(SOLDIERTYPE *pSoldier, INT32 sGridNo) fAlerted = TRUE; if (!fProfile && !fNeutral && !gGameExternalOptions.fAITacticalRetreat && NorthSpot(sGridNo, pSoldier->pathing.bLevel) || - !fProfile && fGreen && CheckDoorNearGridno(sGridNo)) + !fProfile && fGreen && CheckDoorNearGridno(sGridNo) || + Water(sGridNo, pSoldier->pathing.bLevel) && !pSoldier->IsFlanking() || + CorpseWarning(pSoldier, sGridNo, pSoldier->pathing.bLevel)) ubLevel = 1; - if (fAlerted && !fNeutral && (InLightAtNight(sGridNo, pSoldier->pathing.bLevel) || FindNearbyExplosiveStructure(sGridNo, pSoldier->pathing.bLevel))) + if (fAlerted && !fNeutral && + (InLightAtNight(sGridNo, pSoldier->pathing.bLevel) || FindNearbyExplosiveStructure(sGridNo, pSoldier->pathing.bLevel))) ubLevel = 2; - if (DeepWater(sGridNo, pSoldier->pathing.bLevel) || + if (DeepWater(sGridNo, pSoldier->pathing.bLevel) && !pSoldier->IsFlanking() || RedSmokeDanger(sGridNo, pSoldier->pathing.bLevel)) ubLevel = 3; diff --git a/TacticalAI/Attacks.cpp b/TacticalAI/Attacks.cpp index 7fc250d2..6cb99ea6 100644 --- a/TacticalAI/Attacks.cpp +++ b/TacticalAI/Attacks.cpp @@ -2732,11 +2732,13 @@ INT8 CanNPCAttack(SOLDIERTYPE *pSoldier) bCanAttack = TryToReload( pSoldier ); if( bCanAttack == TRUE ) { - PossiblyStartEnemyTaunt( pSoldier, TAUNT_RELOAD ); + if (Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) || GetMagSize(&(pSoldier->inv[HANDPOS])) > 4) + PossiblyStartEnemyTaunt( pSoldier, TAUNT_RELOAD ); } else { - PossiblyStartEnemyTaunt( pSoldier, TAUNT_OUT_OF_AMMO ); + if (Chance(gGameExternalOptions.iChanceSayAnnoyingPhrase) || GetMagSize(&(pSoldier->inv[HANDPOS])) > 4) + PossiblyStartEnemyTaunt( pSoldier, TAUNT_OUT_OF_AMMO ); } } else if (bCanAttack == NOSHOOT_NOWEAPON) diff --git a/TacticalAI/FindLocations.cpp b/TacticalAI/FindLocations.cpp index b93446b9..a78c4347 100644 --- a/TacticalAI/FindLocations.cpp +++ b/TacticalAI/FindLocations.cpp @@ -1526,13 +1526,19 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier) { INT32 sGridNo, sClosestLand = NOWHERE, sPathCost, sShortestPath = 1000; INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset; - INT32 iSearchRange; + INT32 iSearchRange, iIgnoreRange = 0; + INT32 iMaxSearchRange = 35; UINT16 usMovementMode = DetermineMovementMode(pSoldier, AI_ACTION_LEAVE_WATER_GAS); BOOLEAN fFoundReachable = FALSE; + if (!gfTurnBasedAI) + { + iMaxSearchRange = 15; + } + // start with a small search area, and expand it if we're unsuccessful // this should almost never need to search farther than 5 or 10 squares... - for (iSearchRange = 5; iSearchRange <= 35 && (fFoundReachable || iSearchRange <= 5); iSearchRange += 10) + for (iSearchRange = 5; iSearchRange <= iMaxSearchRange && (fFoundReachable || iSearchRange <= 5); iIgnoreRange = iSearchRange, iSearchRange += 10) { //NumMessage("Trying iSearchRange = ", iSearchRange); @@ -1582,6 +1588,12 @@ INT32 FindNearestUngassedLand(SOLDIERTYPE *pSoldier) { for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++) { + // sevenfm: optimization - skip spots checked in previous loop + if (sXOffset <= iIgnoreRange && sXOffset >= -iIgnoreRange && sYOffset <= iIgnoreRange && sYOffset >= -iIgnoreRange) + { + continue; + } + // calculate the next potential gridno sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset); //NumMessage("Testing gridno #",gridno); @@ -1653,7 +1665,8 @@ INT32 FindNearbyDarkerSpot(SOLDIERTYPE *pSoldier) INT32 sGridNo, sClosestSpot = NOWHERE, sPathCost; INT32 iSpotValue, iBestSpotValue = 1000; INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset; - INT32 iSearchRange; + INT32 iSearchRange, iIgnoreRange = 0; + INT32 iMaxSearchRange = 35; INT8 bLightLevel, bCurrLightLevel, bLightDiff; INT32 iRoamRange; INT32 sOrigin; @@ -1664,9 +1677,14 @@ INT32 FindNearbyDarkerSpot(SOLDIERTYPE *pSoldier) iRoamRange = RoamingRange(pSoldier, &sOrigin); + if (!gfTurnBasedAI) + { + iMaxSearchRange = 15; + } + // start with a small search area, and expand it if we're unsuccessful // this should almost never need to search farther than 5 or 10 squares... - for (iSearchRange = 5; iSearchRange <= 25 && (fFoundReachable || iSearchRange <= 5); iSearchRange += 5) + for (iSearchRange = 5; iSearchRange <= iMaxSearchRange && (fFoundReachable || iSearchRange <= 5); iIgnoreRange = iSearchRange, iSearchRange += 10) { // determine maximum horizontal limits sMaxLeft = min(iSearchRange, (pSoldier->sGridNo % MAXCOL)); @@ -1714,6 +1732,12 @@ INT32 FindNearbyDarkerSpot(SOLDIERTYPE *pSoldier) { for (sXOffset = -sMaxLeft; sXOffset <= sMaxRight; sXOffset++) { + // sevenfm: optimization - skip spots checked in previous loop + if (sXOffset <= iIgnoreRange && sXOffset >= -iIgnoreRange && sYOffset <= iIgnoreRange && sYOffset >= -iIgnoreRange) + { + continue; + } + // calculate the next potential gridno sGridNo = pSoldier->sGridNo + sXOffset + (MAXCOL * sYOffset); //NumMessage("Testing gridno #",gridno); @@ -2603,7 +2627,7 @@ INT32 FindFlankingSpot(SOLDIERTYPE *pSoldier, INT32 sPos, INT8 bAction ) INT32 sGridNo; INT32 sBestSpot = NOWHERE; INT32 iSearchRange = 8; // sevenfm: increase search range - INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset; + INT16 sMaxLeft, sMaxRight, sMaxUp, sMaxDown, sXOffset, sYOffset; INT16 sDistanceVisible = VISION_RANGE; DebugMsg ( TOPIC_JA2AI , DBG_LEVEL_3 , String("FindFlankingSpot: orig loc = %d, loc to flank = %d", pSoldier->sGridNo , sPos));