Esempio n. 1
0
// Disable Tactical order mode.
//
void driveDisableTactical(void)
{
	if (driveModeActive() && TacticalActive)
	{
		TacticalActive = false;
	}
}
Esempio n. 2
0
// Disable Tactical order mode.
//
void driveDisableTactical(void)
{
	if(driveModeActive() && TacticalActive)
	{
		CancelTacticalScroll();
		TacticalActive = false;
	}
}
Esempio n. 3
0
// Call whenever the selections change to re initialise drive mode.
//
void driveSelectionChanged(void)
{
	if(driveModeActive()) {
		if(psDrivenDroid) {
			ChangeDriver();
			StartDriverMode(NULL);
		}
	}
}
Esempio n. 4
0
// Call whenever the selections change to re initialise drive mode.
//
void driveSelectionChanged(void)
{
	if(driveModeActive()) {

		if(psDrivenDroid) {
	//		StopDriverMode();
			ChangeDriver();
			StartDriverMode(NULL);
			driveTacticalSelectionChanged();
		}
	}
}
Esempio n. 5
0
// Call this whenever a droid gets killed or removed.
// returns true if ok, returns false if resulted in driving mode being stopped, ie could'nt find
// a selected droid to drive.
//
bool driveDroidKilled(DROID *psDroid)
{
	if(driveModeActive()) {
		if(psDroid == psDrivenDroid) {
			ChangeDriver();

			psDrivenDroid = NULL;
			DeSelectDroid(psDroid);

			if(!StartDriverMode(psDroid))
			{
				return false;
			}
		}
	}

	return true;
}
Esempio n. 6
0
// Find the best nearest target for a droid
// Returns integer representing target priority, -1 if failed
SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, UWORD *targetOrigin)
{
	SDWORD				bestMod = 0,newMod, failure = -1;
	BASE_OBJECT			*psTarget = NULL, *friendlyObj, *bestTarget = NULL, *iter, *targetInQuestion, *tempTarget;
	BOOL				electronic = false;
	STRUCTURE			*targetStructure;
	WEAPON_EFFECT			weaponEffect;
	UWORD				tmpOrigin = ORIGIN_UNKNOWN;

	// reset origin
	if (targetOrigin)
	{
		*targetOrigin = ORIGIN_UNKNOWN;
	}

	//don't bother looking if empty vtol droid
	if (vtolEmpty(psDroid))
	{
		return failure;
	}

	/* Return if have no weapons */
	// The ai orders a non-combat droid to patrol = crash without it...
	if ((psDroid->asWeaps[0].nStat == 0 || psDroid->numWeaps == 0) && psDroid->droidType != DROID_SENSOR)
	{
		return failure;
	}
	// Check if we have a CB target to begin with
	if (!proj_Direct(asWeaponStats + psDroid->asWeaps[weapon_slot].nStat))
	{
		WEAPON_STATS	*psWStats = psWStats = psDroid->asWeaps[weapon_slot].nStat + asWeaponStats;

		bestTarget = aiSearchSensorTargets((BASE_OBJECT *)psDroid, weapon_slot, psWStats, &tmpOrigin);
		bestMod = targetAttackWeight(bestTarget, (BASE_OBJECT *)psDroid, weapon_slot);
	}

	weaponEffect = ((WEAPON_STATS *)(asWeaponStats + psDroid->asWeaps[weapon_slot].nStat))->weaponEffect;

	electronic = electronicDroid(psDroid);

	// Range was previously 9*TILE_UNITS. Increasing this doesn't seem to help much, though. Not sure why.
	gridStartIterate(psDroid->pos.x, psDroid->pos.y, psDroid->sensorRange + 6*TILE_UNITS);
	for (iter = gridIterate(); iter != NULL; iter = gridIterate())
	{
		friendlyObj = NULL;
		targetInQuestion = iter;

		/* This is a friendly unit, check if we can reuse its target */
		if(aiCheckAlliances(targetInQuestion->player,psDroid->player))
		{
			friendlyObj = targetInQuestion;
			targetInQuestion = NULL;

			/* Can we see what it is doing? */
			if(friendlyObj->visible[psDroid->player])
			{
				if(friendlyObj->type == OBJ_DROID)
				{
					DROID	*friendlyDroid = (DROID *)friendlyObj;

					/* See if friendly droid has a target */
					tempTarget = friendlyDroid->psActionTarget[0];
					if(tempTarget && !aiObjectIsProbablyDoomed(tempTarget))
					{
						//make sure a weapon droid is targeting it
						if(friendlyDroid->numWeaps > 0)
						{
							// make sure this target wasn't assigned explicitly to this droid
							if(friendlyDroid->order != DORDER_ATTACK)
							{
								// make sure target is near enough
								if (aiDroidHasRange(psDroid, tempTarget, weapon_slot))
								{
									targetInQuestion = tempTarget;		//consider this target
								}
							}
						}
					}
				}
				else if(friendlyObj->type == OBJ_STRUCTURE)
				{
					tempTarget = ((STRUCTURE*)friendlyObj)->psTarget[0];
					if (tempTarget && !aiObjectIsProbablyDoomed(tempTarget) && aiDroidHasRange(psDroid, tempTarget, weapon_slot))
					{
						targetInQuestion = tempTarget;
					}
				}
			}
		}

		if (targetInQuestion != NULL
		    && targetInQuestion != (BASE_OBJECT *)psDroid		// in case friendly unit had me as target
		    && (targetInQuestion->type == OBJ_DROID || targetInQuestion->type == OBJ_STRUCTURE || targetInQuestion->type == OBJ_FEATURE)
		    && targetInQuestion->visible[psDroid->player]
		    && !aiCheckAlliances(targetInQuestion->player,psDroid->player)
		    && validTarget((BASE_OBJECT *)psDroid, targetInQuestion, weapon_slot)
		    && aiDroidHasRange(psDroid, targetInQuestion, weapon_slot))
		{
			if (targetInQuestion->type == OBJ_DROID)
			{
				// in multiPlayer - don't attack Transporters with EW
				if (bMultiPlayer)
				{
					// if not electronic then valid target
					if (!electronic
					    || (electronic
					        && ((DROID *)targetInQuestion)->droidType != DROID_TRANSPORTER))
					{
						//only a valid target if NOT a transporter
						psTarget = targetInQuestion;
					}
				}
				else
				{
					psTarget = targetInQuestion;
				}
			}
			else if (targetInQuestion->type == OBJ_STRUCTURE)
			{
				STRUCTURE *psStruct = (STRUCTURE *)targetInQuestion;

				if (electronic)
				{
					/* don't want to target structures with resistance of zero if using electronic warfare */
					if (validStructResistance((STRUCTURE *)targetInQuestion))
					{
						psTarget = targetInQuestion;
					}
				}
				else if (psStruct->asWeaps[weapon_slot].nStat > 0)
				{
					// structure with weapons - go for this
					psTarget = targetInQuestion;
				}
				else if ((psStruct->pStructureType->type != REF_WALL && psStruct->pStructureType->type != REF_WALLCORNER)
				         || driveModeActive() || (bMultiPlayer && !isHumanPlayer(psDroid->player)))
				{
					psTarget = targetInQuestion;
				}
			}
			else if (targetInQuestion->type == OBJ_FEATURE
			         && gameTime - psDroid->lastFrustratedTime < FRUSTRATED_TIME
			         && ((FEATURE *)targetInQuestion)->psStats->damageable
			         && !(game.scavengers && psDroid->player == 7))			// hack to avoid scavs blowing up their nice feature walls
			{
				psTarget = targetInQuestion;
			}

			/* Check if our weapon is most effective against this object */
			if(psTarget != NULL && psTarget == targetInQuestion)		//was assigned?
			{
				newMod = targetAttackWeight(psTarget, (BASE_OBJECT *)psDroid, weapon_slot);

				/* Remember this one if it's our best target so far */
				if( newMod >= 0 && (newMod > bestMod || bestTarget == NULL))
				{
					bestMod = newMod;
					tmpOrigin = ORIGIN_ALLY;
					bestTarget = psTarget;
				}

			}
		}

	}

	if (bestTarget)
	{
		ASSERT(!bestTarget->died, "aiBestNearestTarget: AI gave us a target that is already dead.");
		targetStructure = visGetBlockingWall((BASE_OBJECT *)psDroid, bestTarget);

		/* See if target is blocked by a wall; only affects direct weapons */
		if (proj_Direct(asWeaponStats + psDroid->asWeaps[weapon_slot].nStat)
		 && targetStructure)
		{
			//are we any good against walls?
			if(asStructStrengthModifier[weaponEffect][targetStructure->pStructureType->strength] >= 100)		//can attack atleast with default strength
			{
				bestTarget = (BASE_OBJECT *)targetStructure;			//attack wall
			}
		}

		if (targetOrigin)
		{
			*targetOrigin = tmpOrigin;
		}
		*ppsObj = bestTarget;
		return bestMod;
	}

	return failure;
}
Esempio n. 7
0
/* Do the AI for a droid */
void aiUpdateDroid(DROID *psDroid)
{
	BASE_OBJECT	*psTarget;
	BOOL		lookForTarget,updateTarget;

	ASSERT(psDroid != NULL, "Invalid droid pointer");
	if (!psDroid || isDead((BASE_OBJECT *)psDroid))
	{
		return;
	}

	// HACK: we always want to update orders when NOT running a MP game,
	// and we don't want to update when the droid belongs to another human player
	if (!myResponsibility(psDroid->player) && bMultiPlayer
		  && isHumanPlayer(psDroid->player))
	{
		return;		// we should not order this droid around
	}
	
	lookForTarget = false;
	updateTarget = false;
	
	// look for a target if doing nothing
	if (orderState(psDroid, DORDER_NONE) ||
		orderState(psDroid, DORDER_GUARD) ||
		orderState(psDroid, DORDER_TEMP_HOLD))
	{
		lookForTarget = true;
	}
	// but do not choose another target if doing anything while guarding
	if (orderState(psDroid, DORDER_GUARD) &&
		(psDroid->action != DACTION_NONE))
	{
		lookForTarget = false;
	}
	// except when self-repairing
	if (psDroid->action == DACTION_DROIDREPAIR &&
	    psDroid->psActionTarget[0] == (BASE_OBJECT *)psDroid)
	{
		lookForTarget = true;
	}
	// don't look for a target if sulking
	if (psDroid->action == DACTION_SULK)
	{
		lookForTarget = false;
	}

	/* Only try to update target if already have some target */
	if (psDroid->action == DACTION_ATTACK ||
		psDroid->action == DACTION_MOVEFIRE ||
		psDroid->action == DACTION_MOVETOATTACK ||
		psDroid->action == DACTION_ROTATETOATTACK)
	{
		updateTarget = true;
	}
	if ((orderState(psDroid, DORDER_OBSERVE) || orderState(psDroid, DORDER_ATTACKTARGET)) &&
	    psDroid->psTarget && aiObjectIsProbablyDoomed(psDroid->psTarget))
	{
		lookForTarget = true;
		updateTarget = false;
	}

	/* Don't update target if we are sent to attack and reached
		attack destination (attacking our target) */
	if (orderState(psDroid, DORDER_ATTACK) && psDroid->psActionTarget[0] == psDroid->psTarget)
	{
		updateTarget = false;
	}

	// don't look for a target if there are any queued orders
	if (psDroid->listSize > 0)
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// horrible check to stop droids looking for a target if
	// they would switch to the guard order in the order update loop
	if ((psDroid->order == DORDER_NONE) &&
		(psDroid->player == selectedPlayer) &&
		!isVtolDroid(psDroid) &&
		secondaryGetState(psDroid, DSO_HALTTYPE) == DSS_HALT_GUARD)
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// don't allow units to start attacking if they will switch to guarding the commander
	if(hasCommander(psDroid))
	{
		lookForTarget = false;
		updateTarget = false;
	}

	if(bMultiPlayer && isVtolDroid(psDroid) && isHumanPlayer(psDroid->player))
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// do not look for a target if droid is currently under direct control.
	if(driveModeActive() && (psDroid == driveGetDriven())) {
		lookForTarget = false;
		updateTarget = false;
	}

	// CB and VTOL CB droids can't autotarget.
	if (psDroid->droidType == DROID_SENSOR && !standardSensorDroid(psDroid))
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// do not attack if the attack level is wrong
	if (secondaryGetState(psDroid, DSO_ATTACK_LEVEL) != DSS_ALEV_ALWAYS)
	{
		lookForTarget = false;
	}

	/* For commanders and non-assigned non-commanders:
	 look for a better target once in a while */
	if(!lookForTarget && updateTarget)
	{
		if((psDroid->numWeaps > 0) && !hasCommander(psDroid))	//not assigned to commander
		{
			if((psDroid->id + gameTime)/TARGET_UPD_SKIP_FRAMES != (psDroid->id + gameTime - deltaGameTime)/TARGET_UPD_SKIP_FRAMES)
			{
				unsigned int i;

				(void)updateAttackTarget((BASE_OBJECT*)psDroid, 0); // this function always has to be called on weapon-slot 0 (even if ->numWeaps == 0)

				//updates all targets
				for (i = 1; i < psDroid->numWeaps; ++i)
				{
					(void)updateAttackTarget((BASE_OBJECT*)psDroid, i);
				}
			}
		}
	}

	/* Null target - see if there is an enemy to attack */

	if (lookForTarget && !updateTarget)
	{
		if (psDroid->droidType == DROID_SENSOR)
		{
			if (aiChooseSensorTarget((BASE_OBJECT *)psDroid, &psTarget))
			{
				orderDroidObj(psDroid, DORDER_OBSERVE, psTarget);
			}
		}
		else
		{
			if (aiChooseTarget((BASE_OBJECT *)psDroid, &psTarget, 0, true, NULL))
			{
				orderDroidObj(psDroid, DORDER_ATTACKTARGET, psTarget);
			}
		}
	}
}
Esempio n. 8
0
/* Do the AI for a droid */
void aiUpdateDroid(DROID *psDroid)
{
	BASE_OBJECT	*psTarget;
	bool		lookForTarget, updateTarget;

	ASSERT(psDroid != NULL, "Invalid droid pointer");
	if (!psDroid || isDead((BASE_OBJECT *)psDroid))
	{
		return;
	}

	lookForTarget = false;
	updateTarget = false;

	// look for a target if doing nothing
	if (orderState(psDroid, DORDER_NONE) ||
	    orderState(psDroid, DORDER_GUARD) ||
	    orderState(psDroid, DORDER_HOLD))
	{
		lookForTarget = true;
	}
	// but do not choose another target if doing anything while guarding
	// exception for sensors, to allow re-targetting when target is doomed
	if (orderState(psDroid, DORDER_GUARD) && psDroid->action != DACTION_NONE && psDroid->droidType != DROID_SENSOR)
	{
		lookForTarget = false;
	}
	// don't look for a target if sulking
	if (psDroid->action == DACTION_SULK)
	{
		lookForTarget = false;
	}

	/* Only try to update target if already have some target */
	if (psDroid->action == DACTION_ATTACK ||
	    psDroid->action == DACTION_MOVEFIRE ||
	    psDroid->action == DACTION_MOVETOATTACK ||
	    psDroid->action == DACTION_ROTATETOATTACK)
	{
		updateTarget = true;
	}
	if ((orderState(psDroid, DORDER_OBSERVE) || orderState(psDroid, DORDER_ATTACKTARGET)) &&
	    psDroid->order.psObj && psDroid->order.psObj->died)
	{
		lookForTarget = true;
		updateTarget = false;
	}

	/* Don't update target if we are sent to attack and reached attack destination (attacking our target) */
	if (orderState(psDroid, DORDER_ATTACK) && psDroid->psActionTarget[0] == psDroid->order.psObj)
	{
		updateTarget = false;
	}

	// don't look for a target if there are any queued orders
	if (psDroid->listSize > 0)
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// don't allow units to start attacking if they will switch to guarding the commander
	if (hasCommander(psDroid))
	{
		lookForTarget = false;
		updateTarget = false;
	}

	if (bMultiPlayer && isVtolDroid(psDroid) && isHumanPlayer(psDroid->player))
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// do not look for a target if droid is currently under direct control.
	if (driveModeActive() && (psDroid == driveGetDriven()))
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// CB and VTOL CB droids can't autotarget.
	if (psDroid->droidType == DROID_SENSOR && !standardSensorDroid(psDroid))
	{
		lookForTarget = false;
		updateTarget = false;
	}

	// do not attack if the attack level is wrong
	if (secondaryGetState(psDroid, DSO_ATTACK_LEVEL) != DSS_ALEV_ALWAYS)
	{
		lookForTarget = false;
	}

	/* For commanders and non-assigned non-commanders: look for a better target once in a while */
	if (!lookForTarget && updateTarget && psDroid->numWeaps > 0 && !hasCommander(psDroid)
	    && (psDroid->id + gameTime) / TARGET_UPD_SKIP_FRAMES != (psDroid->id + gameTime - deltaGameTime) / TARGET_UPD_SKIP_FRAMES)
	{
		for (int i = 0; i < psDroid->numWeaps; ++i)
		{
			updateAttackTarget((BASE_OBJECT *)psDroid, i);
		}
	}

	/* Null target - see if there is an enemy to attack */

	if (lookForTarget && !updateTarget)
	{
		if (psDroid->droidType == DROID_SENSOR)
		{
			if (aiChooseSensorTarget((BASE_OBJECT *)psDroid, &psTarget))
			{
				actionDroid(psDroid, DACTION_OBSERVE, psTarget);
			}
		}
		else
		{
			if (aiChooseTarget((BASE_OBJECT *)psDroid, &psTarget, 0, true, NULL))
			{
				actionDroid(psDroid, DACTION_ATTACK, psTarget);
			}
		}
	}
}