Oolite
Loading...
Searching...
No Matches
ShipEntity Class Reference

#include <ShipEntity.h>

+ Inheritance diagram for ShipEntity:
+ Collaboration diagram for ShipEntity:

Instance Methods

(void) - setStateMachine:
 
(void) - setAI:
 
(AI *) - getAI
 
(BOOL) - hasAutoAI
 
(BOOL) - hasNewAI
 
(void) - setShipScript:
 
(void) - removeScript
 
(OOScript *) - shipScript
 
(OOScript *) - shipAIScript
 
(OOTimeAbsolute- shipAIScriptWakeTime
 
(void) - setAIScriptWakeTime:
 
(double) - frustration
 
(void) - setLaunchDelay:
 
(void) - interpretAIMessage:
 
(GLfloat) - accuracy
 
(void) - setAccuracy:
 
(OOMesh *) - mesh
 
(void) - setMesh:
 
(BoundingBox) - totalBoundingBox
 
(Vector) - forwardVector
 
(Vector) - upVector
 
(Vector) - rightVector
 
(NSArray *) - subEntities
 
(NSUInteger) - subEntityCount
 
(BOOL) - hasSubEntity:
 
(NSEnumerator *) - subEntityEnumerator
 
(NSEnumerator *) - shipSubEntityEnumerator
 
(NSEnumerator *) - flasherEnumerator
 
(NSEnumerator *) - exhaustEnumerator
 
(ShipEntity *) - subEntityTakingDamage
 
(void) - setSubEntityTakingDamage:
 
(void) - clearSubEntities
 
(Quaternion) - subEntityRotationalVelocity
 
(void) - setSubEntityRotationalVelocity:
 
(NSString *) - serializeShipSubEntities
 
(void) - deserializeShipSubEntitiesFrom:
 
(NSUInteger) - maxShipSubEntities
 
(void) - setSubIdx:
 
(NSUInteger) - subIdx
 
(Octree *) - octree
 
(float) - volume
 
(GLfloat) - doesHitLine:v0:
 
(GLfloat) - doesHitLine:v0:v1:
 
(GLfloat) - doesHitLine:v0:withPosition:andIJK:i:j:
 
(BoundingBox) - findBoundingBoxRelativeToPosition:InVectors:i:j:
 
(HPVector) - absoluteTractorPosition
 
(void) - setIsBoulder:
 
(BOOL) - isBoulder
 
(BOOL) - isMinable
 
(BOOL) - countsAsKill
 
(void) - setUpEscorts
 
(void) - updateEscortFormation
 
(id) - initWithKey:definition:
 
(BOOL) - setUpFromDictionary:
 
(BOOL) - setUpShipFromDictionary:
 
(BOOL) - setUpSubEntities
 
(BOOL) - setUpOneStandardSubentity:asTurret:
 
(GLfloat) - frustumRadius
 
(NSString *) - shipDataKey
 
(NSString *) - shipDataKeyAutoRole
 
(void) - setShipDataKey:
 
(NSDictionary *) - shipInfoDictionary
 
(NSArray *) - getWeaponOffsetFrom:withKey:inMode:
 
(NSArray *) - aftWeaponOffset
 
(NSArray *) - forwardWeaponOffset
 
(NSArray *) - portWeaponOffset
 
(NSArray *) - starboardWeaponOffset
 
(BOOL) - hasAutoWeapons
 
(BOOL) - isFrangible
 
(BOOL) - suppressFlightNotifications
 
(void) - respondToAttackFrom:becauseOf:
 
(OOWeaponFacingSet- weaponFacings
 
(BOOL) - hasEquipmentItem:includeWeapons:whileLoading:
 
(BOOL) - hasEquipmentItem:
 
(NSUInteger) - countEquipmentItem:
 
(NSString *) - equipmentItemProviding:
 
(BOOL) - hasEquipmentItemProviding:
 
(BOOL) - hasAllEquipment:includeWeapons:whileLoading:
 
(BOOL) - hasAllEquipment:
 
(BOOL) - setWeaponMount:toWeapon:
 
(BOOL) - canAddEquipment:inContext:
 
(BOOL) - equipmentValidToAdd:inContext:
 
(BOOL) - equipmentValidToAdd:whileLoading:inContext:
 
(BOOL) - addEquipmentItem:inContext:
 
(BOOL) - addEquipmentItem:withValidation:inContext:
 
(BOOL) - hasHyperspaceMotor
 
(float) - hyperspaceSpinTime
 
(void) - setHyperspaceSpinTime:
 
(NSEnumerator *) - equipmentEnumerator
 
(NSUInteger) - equipmentCount
 
(void) - removeEquipmentItem:
 
(void) - removeAllEquipment
 
(OOEquipmentType *) - selectMissile
 
(OOCreditsQuantity- removeMissiles
 
(BOOL) - hasOneEquipmentItem:includeWeapons:whileLoading:
 
(BOOL) - hasOneEquipmentItem:includeMissiles:whileLoading:
 
(BOOL) - hasPrimaryWeapon:
 
(BOOL) - removeExternalStore:
 
(NSUInteger) - parcelCount
 
(NSUInteger) - passengerCount
 
(NSUInteger) - passengerCapacity
 
(NSUInteger) - missileCount
 
(NSUInteger) - missileCapacity
 
(NSUInteger) - extraCargo
 
(BOOL) - hasScoop
 
(BOOL) - hasFuelScoop
 
(BOOL) - hasCargoScoop
 
(BOOL) - hasECM
 
(BOOL) - hasCloakingDevice
 
(BOOL) - hasMilitaryScannerFilter
 
(BOOL) - hasMilitaryJammer
 
(BOOL) - hasExpandedCargoBay
 
(BOOL) - hasShieldBooster
 
(BOOL) - hasMilitaryShieldEnhancer
 
(BOOL) - hasHeatShield
 
(BOOL) - hasFuelInjection
 
(BOOL) - hasCascadeMine
 
(BOOL) - hasEscapePod
 
(BOOL) - hasDockingComputer
 
(BOOL) - hasGalacticHyperdrive
 
(float) - shieldBoostFactor
 
(float) - maxForwardShieldLevel
 
(float) - maxAftShieldLevel
 
(float) - shieldRechargeRate
 
(double) - maxHyperspaceDistance
 
(float) - afterburnerFactor
 
(float) - afterburnerRate
 
(void) - setAfterburnerFactor:
 
(void) - setAfterburnerRate:
 
(float) - maxThrust
 
(float) - thrust
 
(void) - setMaxThrust:
 
(void) - setMaxFlightPitch:
 
(void) - setMaxFlightSpeed:
 
(void) - setMaxFlightRoll:
 
(void) - setMaxFlightYaw:
 
(void) - setEnergyRechargeRate:
 
(void) - processBehaviour:
 
(void) - behaviour_stop_still:
 
(void) - behaviour_idle:
 
(void) - behaviour_tumble:
 
(void) - behaviour_tractored:
 
(void) - behaviour_track_target:
 
(void) - behaviour_intercept_target:
 
(void) - behaviour_attack_target:
 
(void) - behaviour_attack_slow_dogfight:
 
(void) - behaviour_evasive_action:
 
(void) - behaviour_attack_break_off_target:
 
(void) - behaviour_fly_to_target_six:
 
(void) - behaviour_attack_mining_target:
 
(void) - behaviour_attack_fly_to_target:
 
(void) - behaviour_attack_fly_from_target:
 
(void) - behaviour_running_defense:
 
(void) - behaviour_flee_target:
 
(void) - behaviour_attack_broadside:
 
(void) - behaviour_attack_broadside_left:
 
(void) - behaviour_attack_broadside_right:
 
(void) - behaviour_close_to_broadside_range:
 
(void) - behaviour_close_with_target:
 
(void) - behaviour_attack_broadside_target:leftside:
 
(void) - behaviour_attack_sniper:
 
(void) - behaviour_fly_range_from_destination:
 
(void) - behaviour_face_destination:
 
(void) - behaviour_land_on_planet:
 
(void) - behaviour_formation_form_up:
 
(void) - behaviour_fly_to_destination:
 
(void) - behaviour_fly_from_destination:
 
(void) - behaviour_avoid_collision:
 
(void) - behaviour_track_as_turret:
 
(void) - behaviour_fly_thru_navpoints:
 
(void) - behaviour_scripted_ai:
 
(float) - reactionTime
 
(void) - setReactionTime:
 
(HPVector) - calculateTargetPosition
 
(void) - startTrackingCurve
 
(void) - updateTrackingCurve
 
(void) - calculateTrackingCurve
 
(GLfloat *) - scannerDisplayColorForShip:otherShip:isHostile:flash:scannerDisplayColor1:scannerDisplayColor2:scannerDisplayColorH1:
 
(void) - setScannerDisplayColor1:
 
(void) - setScannerDisplayColor2:
 
(OOColor *) - scannerDisplayColor1
 
(OOColor *) - scannerDisplayColor2
 
(void) - setScannerDisplayColorHostile1:
 
(void) - setScannerDisplayColorHostile2:
 
(OOColor *) - scannerDisplayColorHostile1
 
(OOColor *) - scannerDisplayColorHostile2
 
(BOOL) - isCloaked
 
(void) - setCloaked:
 
(BOOL) - hasAutoCloak
 
(void) - setAutoCloak:
 
(void) - applyThrust:
 
(void) - applyAttitudeChanges:
 
(void) - avoidCollision
 
(void) - resumePostProximityAlert
 
(double) - messageTime
 
(void) - setMessageTime:
 
(OOShipGroup *) - group
 
(void) - setGroup:
 
(OOShipGroup *) - escortGroup
 
(void) - setEscortGroup:
 
(OOShipGroup *) - stationGroup
 
(BOOL) - hasEscorts
 
(NSEnumerator *) - escortEnumerator
 
(NSArray *) - escortArray
 
(uint8_t) - escortCount
 
(uint8_t) - pendingEscortCount
 
(void) - setPendingEscortCount:
 
(uint8_t) - maxEscortCount
 
(void) - setMaxEscortCount:
 
(NSUInteger) - turretCount
 
(NSString *) - name
 
(NSString *) - shipUniqueName
 
(NSString *) - shipClassName
 
(NSString *) - displayName
 
(NSString *) - scanDescription
 
(NSString *) - scanDescriptionForScripting
 
(void) - setName:
 
(void) - setShipUniqueName:
 
(void) - setShipClassName:
 
(void) - setDisplayName:
 
(void) - setScanDescription:
 
(NSString *) - identFromShip:
 
(BOOL) - hasRole:
 
(OORoleSet *) - roleSet
 
(void) - addRole:
 
(void) - addRole:withProbability:
 
(void) - removeRole:
 
(NSString *) - primaryRole
 
(void) - setPrimaryRole:
 
(BOOL) - hasPrimaryRole:
 
(BOOL) - isPolice
 
(BOOL) - isThargoid
 
(BOOL) - isTrader
 
(BOOL) - isPirate
 
(BOOL) - isMissile
 
(BOOL) - isMine
 
(BOOL) - isWeapon
 
(BOOL) - isEscort
 
(BOOL) - isShuttle
 
(BOOL) - isTurret
 
(BOOL) - isPirateVictim
 
(BOOL) - isExplicitlyUnpiloted
 
(BOOL) - isUnpiloted
 
(OOAlertCondition- alertCondition
 
(OOAlertCondition- realAlertCondition
 
(BOOL) - hasHostileTarget
 
(BOOL) - isHostileTo:
 
(NSUInteger) - defenseTargetCount
 
(NSArray *) - allDefenseTargets
 
(NSEnumerator *) - defenseTargetEnumerator
 
(void) - validateDefenseTargets
 
(BOOL) - addDefenseTarget:
 
(BOOL) - isDefenseTarget:
 
(void) - removeDefenseTarget:
 
(void) - removeAllDefenseTargets
 
(NSArray *) - collisionExceptions
 
(void) - addCollisionException:
 
(void) - removeCollisionException:
 
(BOOL) - collisionExceptedFor:
 
(GLfloat) - weaponRange
 
(void) - setWeaponRange:
 
(void) - setWeaponDataFromType:
 
(float) - energyRechargeRate
 
(float) - weaponRechargeRate
 
(void) - setWeaponRechargeRate:
 
(void) - setWeaponEnergy:
 
(OOWeaponFacing- currentWeaponFacing
 
(GLfloat) - scannerRange
 
(void) - setScannerRange:
 
(Vector) - reference
 
(void) - setReference:
 
(BOOL) - reportAIMessages
 
(void) - setReportAIMessages:
 
(void) - transitionToAegisNone
 
(OOPlanetEntity *) - findNearestPlanet
 
(Entity< OOStellarBody > *) - findNearestStellarBody
 
(OOPlanetEntity *) - findNearestPlanetExcludingMoons
 
(OOAegisStatus- checkForAegis
 
(void) - forceAegisCheck
 
(BOOL) - withinStationAegis
 
(void) - setLastAegisLock:
 
(OOSystemID- homeSystem
 
(OOSystemID- destinationSystem
 
(void) - setHomeSystem:
 
(void) - setDestinationSystem:
 
(NSArray *) - crew
 
(NSArray *) - crewForScripting
 
(void) - setCrew:
 
(void) - setSingleCrewWithRole:
 
(OOFuelQuantity- fuel
 
(void) - setFuel:
 
(OOFuelQuantity- fuelCapacity
 
(GLfloat) - fuelChargeRate
 
(void) - setRoll:
 
(void) - setRawRoll:
 
(void) - setPitch:
 
(void) - setYaw:
 
(void) - setThrust:
 
(void) - applySticks:
 
(void) - setThrustForDemo:
 
(void) - setBounty:
 
(void) - setBounty:withReason:
 
(void) - setBounty:withReasonAsString:
 
(OOCreditsQuantity- bounty
 
(int- legalStatus
 
(BOOL) - isTemplateCargoPod
 
(void) - setUpCargoType:
 
(void) - setCommodity:andAmount:
 
(void) - setCommodityForPod:andAmount:
 
(OOCommodityType- commodityType
 
(OOCargoQuantity- commodityAmount
 
(OOCargoQuantity- maxAvailableCargoSpace
 
(void) - setMaxAvailableCargoSpace:
 
(OOCargoQuantity- availableCargoSpace
 
(OOCargoQuantity- cargoQuantityOnBoard
 
(OOCargoType- cargoType
 
(NSArray *) - cargoListForScripting
 
(NSMutableArray *) - cargo
 
(void) - setCargo:
 
(BOOL) - addCargo:
 
(BOOL) - removeCargo:amount:
 
(BOOL) - showScoopMessage
 
(NSArray *) - passengerListForScripting
 
(NSArray *) - parcelListForScripting
 
(NSArray *) - contractListForScripting
 
(NSArray *) - equipmentListForScripting
 
(OOWeaponType- weaponTypeIDForFacing:strict:
 
(OOEquipmentType *) - weaponTypeForFacing:strict:
 
(NSArray *) - missilesList
 
(OOCargoFlag- cargoFlag
 
(void) - setCargoFlag:
 
(void) - setSpeed:
 
(double) - desiredSpeed
 
(void) - setDesiredSpeed:
 
(double) - desiredRange
 
(void) - setDesiredRange:
 
(double) - cruiseSpeed
 
(Vector) - thrustVector
 
(void) - setTotalVelocity:
 
(void) - increase_flight_speed:
 
(void) - decrease_flight_speed:
 
(void) - increase_flight_roll:
 
(void) - decrease_flight_roll:
 
(void) - increase_flight_pitch:
 
(void) - decrease_flight_pitch:
 
(void) - increase_flight_yaw:
 
(void) - decrease_flight_yaw:
 
(GLfloat) - flightRoll
 
(GLfloat) - flightPitch
 
(GLfloat) - flightYaw
 
(GLfloat) - flightSpeed
 
(GLfloat) - maxFlightPitch
 
(GLfloat) - maxFlightSpeed
 
(GLfloat) - maxFlightRoll
 
(GLfloat) - maxFlightYaw
 
(GLfloat) - speedFactor
 
(GLfloat) - temperature
 
(void) - setTemperature:
 
(GLfloat) - heatInsulation
 
(void) - setHeatInsulation:
 
(float) - randomEjectaTemperature
 
(float) - randomEjectaTemperatureWithMaxFactor:
 
(int- damage
 
(void) - dealEnergyDamage:atRange:withBias:
 
(void) - dealEnergyDamageWithinDesiredRange
 
(void) - dealMomentumWithinDesiredRange:
 
(void) - noteTakingDamage:from:type:
 
(void) - noteKilledBy:damageType:
 
(void) - getDestroyedBy:damageType:
 
(void) - becomeExplosion
 
(void) - becomeLargeExplosion:
 
(void) - becomeEnergyBlast
 
(void) - broadcastEnergyBlastImminent
 
(void) - setIsWreckage:
 
(BOOL) - showDamage
 
(Vector) - positionOffsetForAlignment:
 
(Vector) - positionOffsetForShipInRotationToAlignment
 
(void) - collectBountyFor:
 
(BoundingBox) - findSubentityBoundingBox
 
(Triangle) - absoluteIJKForSubentity
 
(GLfloat) - weaponRecoveryTime
 
(GLfloat) - laserHeatLevel
 
(GLfloat) - laserHeatLevelAft
 
(GLfloat) - laserHeatLevelForward
 
(GLfloat) - laserHeatLevelPort
 
(GLfloat) - laserHeatLevelStarboard
 
(GLfloat) - hullHeatLevel
 
(GLfloat) - entityPersonality
 
(GLint) - entityPersonalityInt
 
(void) - setEntityPersonalityInt:
 
(void) - setSuppressExplosion:
 
(void) - resetExhaustPlumes
 
(void) - removeExhaust:
 
(void) - removeFlasher:
 
(void) - checkScanner
 
(void) - checkScannerIgnoringUnpowered
 
(ShipEntity **) - scannedShips
 
(int- numberOfScannedShips
 
(Entity *) - foundTarget
 
(Entity *) - primaryAggressor
 
(Entity *) - lastEscortTarget
 
(Entity *) - thankedShip
 
(Entity *) - rememberedShip
 
(Entity *) - proximityAlert
 
(void) - setFoundTarget:
 
(void) - setPrimaryAggressor:
 
(void) - setLastEscortTarget:
 
(void) - setThankedShip:
 
(void) - setRememberedShip:
 
(void) - setProximityAlert:
 
(void) - setTargetStation:
 
(BOOL) - isValidTarget:
 
(void) - addTarget:
 
(void) - removeTarget:
 
(BOOL) - canStillTrackPrimaryTarget
 
(id) - primaryTarget
 
(id) - primaryTargetWithoutValidityCheck
 
(StationEntity *) - targetStation
 
(BOOL) - isFriendlyTo:
 
(ShipEntity *) - shipHitByLaser
 
(void) - noteLostTarget
 
(void) - noteLostTargetAndGoIdle
 
(void) - noteTargetDestroyed:
 
(OOBehaviour- behaviour
 
(void) - setBehaviour:
 
(void) - trackOntoTarget:withDForward:
 
(double) - ballTrackLeadingTarget:atTarget:
 
(GLfloat) - rollToMatchUp:rotating:
 
(GLfloat) - rangeToDestination
 
(double) - trackDestination:delta_t:
 
(void) - setCoordinate:
 
(HPVector) - coordinates
 
(HPVector) - destination
 
(HPVector) - distance_six:
 
(HPVector) - distance_twelve:withOffset:
 
(void) - setEvasiveJink:
 
(void) - evasiveAction:
 
(double) - trackPrimaryTarget:delta_t:
 
(double) - trackSideTarget:delta_t:
 
(double) - missileTrackPrimaryTarget:
 
(double) - rangeToPrimaryTarget
 
(double) - approachAspectToPrimaryTarget
 
(double) - rangeToSecondaryTarget:
 
(BOOL) - hasProximityAlertIgnoringTarget:
 
(GLfloat) - currentAimTolerance
 
(GLfloat) - lookingAtSunWithThresholdAngleCos:
 
(BOOL) - onTarget:withWeapon:
 
(OOTimeDelta- shotTime
 
(void) - resetShotTime
 
(BOOL) - fireMainWeapon:
 
(BOOL) - fireAftWeapon:
 
(BOOL) - firePortWeapon:
 
(BOOL) - fireStarboardWeapon:
 
(BOOL) - fireTurretCannon:
 
(void) - setLaserColor:
 
(void) - setExhaustEmissiveColor:
 
(OOColor *) - laserColor
 
(OOColor *) - exhaustEmissiveColor
 
(BOOL) - fireSubentityLaserShot:
 
(BOOL) - fireDirectLaserShot:
 
(BOOL) - fireDirectLaserDefensiveShot
 
(BOOL) - fireDirectLaserShotAt:
 
(NSArray *) - laserPortOffset:
 
(BOOL) - fireLaserShotInDirection:weaponIdentifier:
 
(void) - adjustMissedShots:
 
(int- missedShots
 
(void) - considerFiringMissile:
 
(Vector) - missileLaunchPosition
 
(ShipEntity *) - fireMissile
 
(ShipEntity *) - fireMissileWithIdentifier:andTarget:
 
(BOOL) - isMissileFlagSet
 
(void) - setIsMissileFlag:
 
(OOTimeDelta- missileLoadTime
 
(void) - setMissileLoadTime:
 
(void) - noticeECM
 
(BOOL) - fireECM
 
(BOOL) - cascadeIfAppropriateWithDamageAmount:cascadeOwner:
 
(BOOL) - activateCloakingDevice
 
(void) - deactivateCloakingDevice
 
(BOOL) - launchCascadeMine
 
(ShipEntity *) - launchEscapeCapsule
 
(OOCommodityType- dumpCargo
 
(ShipEntity *) - dumpCargoItem:
 
(OOCargoType- dumpItem:
 
(void) - manageCollisions
 
(BOOL) - collideWithShip:
 
(void) - adjustVelocity:
 
(void) - addImpactMoment:fraction:
 
(BOOL) - canScoop:
 
(void) - getTractoredBy:
 
(void) - scoopIn:
 
(void) - scoopUp:
 
(void) - scoopUpProcess:processEvents:processMessages:
 
(BOOL) - abandonShip
 
(void) - takeScrapeDamage:from:
 
(void) - takeHeatDamage:
 
(void) - enterDock:
 
(void) - leaveDock:
 
(void) - enterWormhole:
 
(void) - enterWormhole:replacing:
 
(void) - enterWitchspace
 
(void) - leaveWitchspace
 
(BOOL) - witchspaceLeavingEffects
 
(void) - markAsOffender:
 
(void) - markAsOffender:withReason:
 
(void) - switchLightsOn
 
(void) - switchLightsOff
 
(BOOL) - lightsActive
 
(void) - setDestination:
 
(void) - setEscortDestination:
 
(BOOL) - canAcceptEscort:
 
(BOOL) - acceptAsEscort:
 
(void) - deployEscorts
 
(void) - dockEscorts
 
(void) - setTargetToNearestFriendlyStation
 
(void) - setTargetToNearestStation
 
(void) - setTargetToSystemStation
 
(void) - landOnPlanet:
 
(void) - abortDocking
 
(NSDictionary *) - dockingInstructions
 
(void) - broadcastThargoidDestroyed
 
(void) - broadcastHitByLaserFrom:
 
(GLfloat) - sunGlareFilter
 
(void) - setSunGlareFilter:
 
(void) - sendExpandedMessage:toShip:
 
(void) - sendMessage:toShip:withUnpilotedOverride:
 
(void) - broadcastAIMessage:
 
(void) - broadcastMessage:withUnpilotedOverride:
 
(void) - setCommsMessageColor
 
(void) - receiveCommsMessage:from:
 
(void) - commsMessage:withUnpilotedOverride:
 
(BOOL) - markedForFines
 
(BOOL) - markForFines
 
(BOOL) - isMining
 
(void) - spawn:
 
(int- checkShipsInVicinityForWitchJumpExit
 
(BOOL) - trackCloseContacts
 
(void) - setTrackCloseContacts:
 
(void) - setHulk:
 
(BOOL) - isHulk
 
(OOJSScript *) - script
 
(NSDictionary *) - scriptInfo
 
(void) - overrideScriptInfo:
 
(BOOL) - scriptedMisjump
 
(void) - setScriptedMisjump:
 
(GLfloat) - scriptedMisjumpRange
 
(void) - setScriptedMisjumpRange:
 
(Entity *) - entityForShaderProperties
 
(void) - setDemoShip:
 
(BOOL) - isDemoShip
 
(void) - setDemoStartTime:
 
(void) - doScriptEvent:
 
(void) - doScriptEvent:withArgument:
 
(void) - doScriptEvent:withArgument:andArgument:
 
(void) - doScriptEvent:withArguments:
 
(void) - doScriptEvent:withArguments:count:
 
(void) - doScriptEvent:inContext:withArguments:count:
 
(void) - reactToAIMessage:context:
 
(void) - sendAIMessage:
 
(void) - doScriptEvent:andReactToAIMessage:
 
(void) - doScriptEvent:withArgument:andReactToAIMessage:
 
(id) - init [implementation]
 
(id) - initBypassForPlayer [implementation]
 
(NSString *) - repeatString:times: [implementation]
 
(BOOL) - setUpOneSubentity: [implementation]
 
(BOOL) - setUpOneFlasher: [implementation]
 
(void) - dealloc [implementation]
 
(NSString *) - descriptionComponents [implementation]
 
(NSString *) - shortDescriptionComponents [implementation]
 
(BoundingBox) - findBoundingBoxRelativeToPosition:InVectors:_i:_j: [implementation]
 
(void) - wasAddedToUniverse [implementation]
 
(void) - wasRemovedFromUniverse [implementation]
 
(NSString *) - beaconCode [implementation]
 
(void) - setBeaconCode: [implementation]
 
(NSString *) - beaconLabel [implementation]
 
(void) - setBeaconLabel: [implementation]
 
(BOOL) - isVisible [implementation]
 
(BOOL) - isBeacon [implementation]
 
(id< OOHUDBeaconIcon >) - beaconDrawable [implementation]
 
(Entity< OOBeaconEntity > *) - prevBeacon [implementation]
 
(Entity< OOBeaconEntity > *) - nextBeacon [implementation]
 
(void) - setPrevBeacon: [implementation]
 
(void) - setNextBeacon: [implementation]
 
(void) - setUpMixedEscorts [implementation]
 
(void) - setUpOneEscort:inGroup:withRole:atPosition:andCount: [implementation]
 
(OOScanClass- scanClass [implementation]
 
(BOOL) - canCollide [implementation]
 
(ShipEntity *) - doOctreesCollide [implementation]
 
(BOOL) - checkCloseCollisionWith: [implementation]
 
(void) - addSubentityToCollisionRadius: [implementation]
 
(ShipEntity *) - launchPodWithCrew: [implementation]
 
(BOOL) - validForAddToUniverse [implementation]
 
(void) - update: [implementation]
 
(void) - noteFrustration: [implementation]
 
(OOEquipmentType *) - generateMissileEquipmentTypeFrom: [implementation]
 
(OOEquipmentType *) - verifiedMissileTypeFromRole: [implementation]
 
(void) - drawImmediate:translucent: [implementation]
 
(void) - drawDebugStuff [implementation]
 
(void) - drawSubEntityImmediate:translucent: [implementation]
 
(BOOL) - isJammingScanning [implementation]
 
(void) - addSubEntity: [implementation]
 
(void) - setOwner: [implementation]
 
(void) - orientationChanged [implementation]
 
(void) - applyRoll:andClimb: [implementation]
 
(void) - applyRoll:climb:andYaw: [implementation]
 
(OOShipGroup *) - rawEscortGroup [implementation]
 
(NSComparisonResult) - ComparePlanetsBySurfaceDistance [implementation]
 
(Entity< OOStellarBody > *) - lastAegisLock [implementation]
 
(void) - setStatus: [implementation]
 
(void) - rescaleBy: [implementation]
 
(void) - rescaleBy:writeToCache: [implementation]
 
(void) - releaseCargoPodsDebris [implementation]
 
(void) - subEntityDied: [implementation]
 
(void) - subEntityReallyDied: [implementation]
 
(NSComparisonResult) - compareBeaconCodeWith: [implementation]
 
(uint32_t) - randomSeedForShaders [implementation]
 
(void) - setShipHitByLaser: [implementation]
 
(BOOL) - fireWeapon:direction:range: [implementation]
 
(void) - throwSparks [implementation]
 
(Vector) - velocity [implementation]
 
(void) - suppressTargetLost [implementation]
 
(void) - takeEnergyDamage:from:becauseOf:weaponIdentifier: [implementation]
 
(void) - refreshEscortPositions [implementation]
 
(HPVector) - coordinatesForEscortPosition: [implementation]
 
(void) - setTargetToNearestStationIncludingHostiles: [implementation]
 
(BoundingBox) - findBoundingBoxRelativeTo:InVectors:_i:_j: [implementation]
 
(void) - dumpSelfState [implementation]
 
(OOTimeAbsolute- getDemoStartTime [implementation]
 
(void) - doNothing [implementation]
 
(NSString *) - descriptionForObjDump [implementation]
 
(void) - setAITo:
 
(void) - setAIScript:
 
(void) - switchAITo:
 
(void) - scanForHostiles
 
(BOOL) - performHyperSpaceToSpecificSystem:
 
(void) - scanForNearestIncomingMissile
 
(void) - enterTargetWormhole
 
(void) - enterPlayerWormhole
 
(void) - wormholeEscorts
 
(void) - wormholeEntireGroup
 
(BOOL) - suggestEscortTo:
 
(void) - groupAttackTarget
 
(void) - performAttack
 
(void) - performCollect
 
(void) - performEscort
 
(void) - performFaceDestination
 
(void) - performFlee
 
(void) - performFlyToRangeFromDestination
 
(void) - performHold
 
(void) - performIdle
 
(void) - performIntercept
 
(void) - performLandOnPlanet
 
(void) - performMining
 
(void) - performScriptedAI
 
(void) - performScriptedAttackAI
 
(void) - performStop
 
(void) - performTumble
 
(void) - broadcastDistressMessage
 
(void) - broadcastDistressMessageWithDumping:
 
(void) - requestDockingCoordinates
 
(void) - recallDockingInstructions
 
(void) - performBuoyTumble [implementation]
 
(NSDictionary *) - savedShipDictionaryWithContext:
 
(void) - simplifyShipdata:andGetDeletes: [implementation]
 
(void) - checkFoundTarget [implementation]
 
(BOOL) - performHyperSpaceExitReplace: [implementation]
 
(BOOL) - performHyperSpaceExitReplace:toSystem: [implementation]
 
(void) - scanForNearestShipWithPredicate:parameter: [implementation]
 
(void) - scanForNearestShipWithNegatedPredicate:parameter: [implementation]
 
(void) - acceptDistressMessageFrom: [implementation]
 
(BOOL) - launchPatrol [implementation]
 
(NSArray *) - subEntitiesForScript
 
(void) - setTargetForScript:
 
(BOOL) - isVisibleToScripts [implementation]
 
(void) - getJSClass:andPrototype: [implementation]
 
(NSString *) - oo_jsClassName [implementation]
 
(void) - setStateTo: [implementation]
 
(void) - pauseAI: [implementation]
 
(void) - randomPauseAI: [implementation]
 
(void) - dropMessages: [implementation]
 
(void) - debugDumpPendingMessages [implementation]
 
(void) - setDestinationToCurrentLocation [implementation]
 
(void) - setDesiredRangeTo: [implementation]
 
(void) - setDesiredRangeForWaypoint [implementation]
 
(void) - setSpeedTo: [implementation]
 
(void) - setSpeedFactorTo: [implementation]
 
(void) - setSpeedToCruiseSpeed [implementation]
 
(void) - setThrustFactorTo: [implementation]
 
(void) - setTargetToPrimaryAggressor [implementation]
 
(void) - scanForNearestMerchantman [implementation]
 
(void) - scanForRandomMerchantman [implementation]
 
(void) - scanForLoot [implementation]
 
(void) - scanForRandomLoot [implementation]
 
(void) - setTargetToFoundTarget [implementation]
 
(void) - checkForFullHold [implementation]
 
(void) - getWitchspaceEntryCoordinates [implementation]
 
(void) - setDestinationFromCoordinates [implementation]
 
(void) - setCoordinatesFromPosition [implementation]
 
(void) - fightOrFleeMissile [implementation]
 
(void) - setCourseToPlanet [implementation]
 
(void) - setTakeOffFromPlanet [implementation]
 
(void) - landOnPlanet [implementation]
 
(void) - checkTargetLegalStatus [implementation]
 
(void) - checkOwnLegalStatus [implementation]
 
(void) - exitAIWithMessage: [implementation]
 
(void) - setDestinationToTarget [implementation]
 
(void) - setDestinationWithinTarget [implementation]
 
(void) - checkCourseToDestination [implementation]
 
(void) - checkAegis [implementation]
 
(void) - checkEnergy [implementation]
 
(void) - checkHeatInsulation [implementation]
 
(void) - scanForOffenders [implementation]
 
(void) - setCourseToWitchpoint [implementation]
 
(void) - setDestinationToWitchpoint [implementation]
 
(void) - setDestinationToStationBeacon [implementation]
 
(void) - performHyperSpaceExit [implementation]
 
(void) - performHyperSpaceExitWithoutReplacing [implementation]
 
(void) - wormholeGroup [implementation]
 
(void) - commsMessage: [implementation]
 
(void) - commsMessageByUnpiloted: [implementation]
 
(void) - ejectCargo [implementation]
 
(void) - scanForThargoid [implementation]
 
(void) - scanForNonThargoid [implementation]
 
(void) - thargonCheckMother [implementation]
 
(void) - becomeUncontrolledThargon [implementation]
 
(void) - checkDistanceTravelled [implementation]
 
(void) - fightOrFleeHostiles [implementation]
 
(void) - suggestEscort [implementation]
 
(void) - escortCheckMother [implementation]
 
(void) - checkGroupOddsVersusTarget [implementation]
 
(void) - scanForFormationLeader [implementation]
 
(void) - messageMother: [implementation]
 
(void) - setPlanetPatrolCoordinates [implementation]
 
(void) - setSunSkimStartCoordinates [implementation]
 
(void) - setSunSkimEndCoordinates [implementation]
 
(void) - setSunSkimExitCoordinates [implementation]
 
(void) - patrolReportIn [implementation]
 
(void) - checkForMotherStation [implementation]
 
(void) - sendTargetCommsMessage: [implementation]
 
(void) - markTargetForFines [implementation]
 
(void) - markTargetForOffence: [implementation]
 
(void) - storeTarget [implementation]
 
(void) - recallStoredTarget [implementation]
 
(void) - scanForRocks [implementation]
 
(void) - setDestinationToDockingAbort [implementation]
 
(void) - requestNewTarget [implementation]
 
(void) - rollD: [implementation]
 
(void) - scanForNearestShipWithPrimaryRole: [implementation]
 
(void) - scanForNearestShipHavingRole: [implementation]
 
(void) - scanForNearestShipWithAnyPrimaryRole: [implementation]
 
(void) - scanForNearestShipHavingAnyRole: [implementation]
 
(void) - scanForNearestShipWithScanClass: [implementation]
 
(void) - scanForNearestShipWithoutPrimaryRole: [implementation]
 
(void) - scanForNearestShipNotHavingRole: [implementation]
 
(void) - scanForNearestShipWithoutAnyPrimaryRole: [implementation]
 
(void) - scanForNearestShipNotHavingAnyRole: [implementation]
 
(void) - scanForNearestShipWithoutScanClass: [implementation]
 
(void) - setCoordinates: [implementation]
 
(void) - checkForNormalSpace [implementation]
 
(void) - setTargetToRandomStation [implementation]
 
(void) - setTargetToLastStation [implementation]
 
(void) - addFuel: [implementation]
 
(void) - scriptActionOnTarget: [implementation]
 
(void) - sendScriptMessage: [implementation]
 
(void) - ai_throwSparks [implementation]
 
(void) - explodeSelf [implementation]
 
(void) - ai_debugMessage: [implementation]
 
(void) - targetFirstBeaconWithCode: [implementation]
 
(void) - targetNextBeaconWithCode: [implementation]
 
(void) - setRacepointsFromTarget [implementation]
 
(void) - performFlyRacepoints [implementation]
 
(void) - addPrimaryAggressorAsDefenseTarget [implementation]
 
(void) - addFoundTargetAsDefenseTarget [implementation]
 
(void) - findNewDefenseTarget [implementation]
 
(void) - setDestinationToJinkPosition [implementation]
 
(void) - disengageAutopilot [implementation]
 
(void) - messageSelf: [implementation]
 
(void) - scanForNearestShipMatchingPredicate: [implementation]
 
(void) - safeScriptActionOnTarget: [implementation]
 
(ShipEntity *) - ejectShipOfType:
 
(ShipEntity *) - ejectShipOfRole:
 
(NSArray *) - spawnShipsWithRole:count:
 
(BOOL) - isShipWithSubEntityShip: [implementation]
 
- Instance Methods inherited from OOEntityWithDrawable
(OODrawable *) - drawable
 
(void) - setDrawable:
 
(double) - findCollisionRadius [implementation]
 
(NSSet *) - allTextures [implementation]
 
- Instance Methods inherited from Entity
(NSUInteger) - sessionID
 
(BOOL) - isShip
 
(BOOL) - isDock
 
(BOOL) - isStation
 
(BOOL) - isSubEntity
 
(BOOL) - isPlayer
 
(BOOL) - isPlanet
 
(BOOL) - isSun
 
(BOOL) - isSunlit
 
(BOOL) - isStellarObject
 
(BOOL) - isSky
 
(BOOL) - isWormhole
 
(BOOL) - isEffect
 
(BOOL) - isVisualEffect
 
(BOOL) - isWaypoint
 
(void) - addToLinkedLists
 
(void) - removeFromLinkedLists
 
(void) - updateLinkedLists
 
(void) - warnAboutHostiles
 
(CollisionRegion *) - collisionRegion
 
(void) - setCollisionRegion:
 
(void) - setUniversalID:
 
(OOUniversalID- universalID
 
(BOOL) - throwingSparks
 
(void) - setThrowSparks:
 
(id) - owner
 
(ShipEntity *) - parentEntity
 
(ShipEntity *) - rootShipEntity
 
(void) - setPosition:
 
(void) - setPositionX:y:z:
 
(HPVector) - position
 
(Vector) - cameraRelativePosition
 
(GLfloat) - cameraRangeFront
 
(GLfloat) - cameraRangeBack
 
(void) - updateCameraRelativePosition
 
(Vector) - vectorTo:
 
(HPVector) - absolutePositionForSubentity
 
(HPVector) - absolutePositionForSubentityOffset:
 
(double) - zeroDistance
 
(double) - camZeroDistance
 
(NSComparisonResult) - compareZeroDistance:
 
(BoundingBox) - boundingBox
 
(GLfloat) - mass
 
(Quaternion) - orientation
 
(void) - setOrientation:
 
(Quaternion) - normalOrientation
 
(void) - setNormalOrientation:
 
(void) - setVelocity:
 
(double) - speed
 
(GLfloat) - distanceTravelled
 
(void) - setDistanceTravelled:
 
(OOEntityStatus- status
 
(void) - setScanClass:
 
(void) - setEnergy:
 
(GLfloat) - energy
 
(void) - setMaxEnergy:
 
(GLfloat) - maxEnergy
 
(void) - moveForward:
 
(OOMatrix) - rotationMatrix
 
(OOMatrix) - drawRotationMatrix
 
(OOMatrix) - transformationMatrix
 
(OOMatrix) - drawTransformationMatrix
 
(GLfloat) - collisionRadius
 
(void) - setCollisionRadius:
 
(NSMutableArray *) - collisionArray
 
(void) - applyVelocity:
 
(void) - dumpState
 
(NSUInteger) - lastDrawCounter
 
(void) - setLastDrawCounter:
 
(BOOL) - isInSpace
 
(BOOL) - isImmuneToBreakPatternHide
 
(GLfloat) - universalTime
 
(GLfloat) - spawnTime
 
(GLfloat) - timeElapsedSinceSpawn
 
(void) - setAtmosphereFogging:
 
(OOColor *) - fogUniform
 
(NSString *) - descriptionForObjDumpBasic
 
(BOOL) - checkLinkedLists [implementation]
 
(id< OOWeakReferenceSupport >) - superShaderBindingTarget [implementation]
 
(Vector) - relativePosition [implementation]
 
(BOOL) - isBreakPattern
 
(void) - inspect [implementation]
 
(BOOL) - isECMBlast
 
(BOOL) - isExhaust
 
(BOOL) - isFlasher
 
(void) - deleteJSSelf
 
(jsval) - oo_jsValueInContext: [implementation]
 
(BOOL) - isCascadeWeapon
 
(BOOL) - isPlayerLikeShip
 
(GLfloat) - clock [implementation]
 
(unsigned) - pseudoFixedD100 [implementation]
 
(unsigned) - pseudoFixedD256 [implementation]
 
(unsigned) - systemGovernment [implementation]
 
(unsigned) - systemEconomy [implementation]
 
(unsigned) - systemTechLevel [implementation]
 
(unsigned) - systemPopulation [implementation]
 
(unsigned) - systemProductivity [implementation]
 
- Instance Methods inherited from OOWeakRefObject
(id) - weakSelf
 
(id) - weakRetain [implementation]
 
(void) - weakRefDied: [implementation]
 
- Instance Methods inherited from <OOWeakReferenceSupport>
(id) - OO_RETURNS_RETAINED
 

Class Methods

(static BOOL) + IsBehaviourHostile [implementation]
 
(static float) + SurfaceDistanceSqaredV [implementation]
 
(static float) + SurfaceDistanceSqared [implementation]
 
(static BOOL) + AuthorityPredicate [implementation]
 
(id) + shipRestoredFromDictionary:useFallback:context:
 

Public Attributes

OOTimeDelta shot_time
 
Vector v_forward
 
Vector v_up
 
Vector v_right
 
HPVector _destination
 
GLfloat desired_range
 
GLfloat desired_speed
 
GLfloat stick_roll
 
GLfloat stick_pitch
 
GLfloat stick_yaw
 
OOBehaviour behaviour
 
BoundingBox totalBoundingBox
 
- Public Attributes inherited from Entity
OOUniversalID universalID
 
unsigned isShip: 1
 
unsigned isStation: 1
 
unsigned isPlayer: 1
 
unsigned isWormhole: 1
 
unsigned isSubEntity: 1
 
unsigned hasMoved: 1
 
unsigned hasRotated: 1
 
unsigned hasCollided: 1
 
unsigned isSunlit: 1
 
unsigned collisionTestFilter: 2
 
unsigned throw_sparks: 1
 
unsigned isImmuneToBreakPatternHide: 1
 
unsigned isExplicitlyNotMainStation: 1
 
unsigned isVisualEffect: 1
 
OOScanClass scanClass
 
GLfloat zero_distance
 
GLfloat cam_zero_distance
 
GLfloat no_draw_distance
 
GLfloat collision_radius
 
HPVector position
 
Vector cameraRelativePosition
 
Quaternion orientation
 
OOColoratmosphereFogging
 
int zero_index
 
Entityx_previous
 
Entityx_next
 
Entityy_previous
 
Entityy_next
 
Entityz_previous
 
Entityz_next
 
Entitycollision_chain
 
OOUniversalID shadingEntityID
 
Entitycollider
 
CollisionRegioncollisionRegion
 

Protected Attributes

NSDictionary * shipinfoDictionary
 
Quaternion subentityRotationalVelocity
 
OOJSScriptscript
 
OOJSScriptaiScript
 
OOTimeAbsolute aiScriptWakeTime
 
NSDictionary * dockingInstructions
 
OOColorlaser_color
 
OOColordefault_laser_color
 
OOColorexhaust_emissive_color
 
OOColorscanner_display_color1
 
OOColorscanner_display_color2
 
OOColorscanner_display_color_hostile1
 
OOColorscanner_display_color_hostile2
 
GLfloat maxFlightSpeed
 
GLfloat max_flight_roll
 
GLfloat max_flight_pitch
 
GLfloat max_flight_yaw
 
GLfloat cruiseSpeed
 
GLfloat max_thrust
 
GLfloat thrust
 
float hyperspaceMotorSpinTime
 
unsigned military_jammer_active: 1
 
unsigned docking_match_rotation: 1
 
unsigned pitching_over: 1
 
unsigned rolling_over: 1
 
unsigned reportAIMessages: 1
 
unsigned being_mined: 1
 
unsigned being_fined: 1
 
unsigned isHulk: 1
 
unsigned trackCloseContacts: 1
 
unsigned isNearPlanetSurface: 1
 
unsigned isFrangible: 1
 
unsigned cloaking_device_active: 1
 
unsigned cloakPassive: 1
 
unsigned cloakAutomatic: 1
 
unsigned canFragment: 1
 
unsigned isWreckage: 1
 
unsigned _showDamage: 1
 
unsigned suppressExplosion: 1
 
unsigned suppressAegisMessages: 1
 
unsigned isMissile: 1
 
unsigned _explicitlyUnpiloted: 1
 
unsigned hasScoopMessage: 1
 
unsigned scripted_misjump: 1
 
unsigned haveExecutedSpawnAction: 1
 
unsigned haveStartedJSAI: 1
 
unsigned noRocks: 1
 
unsigned _lightsActive: 1
 
GLfloat _scriptedMisjumpRange
 
GLfloat sunGlareFilter
 
OOFuelQuantity fuel
 
GLfloat fuel_accumulator
 
GLfloat afterburner_rate
 
GLfloat afterburner_speed_factor
 
OOCargoQuantity likely_cargo
 
OOCargoQuantity max_cargo
 
OOCargoQuantity extra_cargo
 
OOCargoQuantity equipment_weight
 
OOCargoType cargo_type
 
OOCargoFlag cargo_flag
 
OOCreditsQuantity bounty
 
GLfloat energy_recharge_rate
 
OOWeaponFacingSet weapon_facings
 
OOWeaponType forward_weapon_type
 
OOWeaponType aft_weapon_type
 
OOWeaponType port_weapon_type
 
OOWeaponType starboard_weapon_type
 
GLfloat weapon_damage
 
GLfloat weapon_damage_override
 
GLfloat weaponRange
 
OOWeaponFacing currentWeaponFacing
 
GLfloat weapon_energy_use
 
GLfloat weapon_temp
 
GLfloat weapon_shot_temperature
 
GLfloat forward_weapon_temp
 
GLfloat aft_weapon_temp
 
GLfloat port_weapon_temp
 
GLfloat starboard_weapon_temp
 
GLfloat scannerRange
 
unsigned missiles
 
unsigned max_missiles
 
NSString * _missileRole
 
OOTimeDelta missile_load_time
 
OOTimeAbsolute missile_launch_time
 
AIshipAI
 
NSString * name
 
NSString * shipUniqueName
 
NSString * shipClassName
 
NSString * displayName
 
NSString * scan_description
 
OORoleSetroleSet
 
NSString * primaryRole
 
NSArray * explosionType
 
Vector jink
 
HPVector coordinates
 
Vector reference
 
NSUInteger _subIdx
 
NSUInteger _maxShipSubIdx
 
double launch_time
 
double launch_delay
 
OOUniversalID planetForLanding
 
GLfloat frustration
 
GLfloat success_factor
 
int patrol_counter
 
NSMutableDictionary * previousCondition
 
float weapon_recharge_rate
 
int shot_counter
 
OOTimeAbsolute cargo_dump_time
 
OOTimeAbsolute last_shot_time
 
NSMutableArray * cargo
 
OOCommodityType commodity_type
 
OOCargoQuantity commodity_amount
 
GLfloat flightSpeed
 
GLfloat flightRoll
 
GLfloat flightPitch
 
GLfloat flightYaw
 
GLfloat accuracy
 
GLfloat pitch_tolerance
 
GLfloat aim_tolerance
 
int _missed_shots
 
OOAegisStatus aegis_status
 
OOSystemID home_system
 
OOSystemID destination_system
 
double messageTime
 
double next_spark_time
 
Vector collision_vector
 
GLfloat _scaleFactor
 
BOOL _multiplyWeapons
 
NSArray * forwardWeaponOffset
 
NSArray * aftWeaponOffset
 
NSArray * portWeaponOffset
 
NSArray * starboardWeaponOffset
 
NSArray * crew
 
NSMutableDictionary * closeContactsInfo
 
NSString * lastRadioMessage
 
Vector tractor_position
 
float ship_temperature
 
ShipEntityscanned_ships [MAX_SCAN_NUMBER+1]
 
GLfloat distance2_scanned_ships [MAX_SCAN_NUMBER+1]
 
unsigned n_scanned_ships
 
HPVector navpoints [32]
 
unsigned next_navpoint_index
 
unsigned number_of_navpoints
 
Octreeoctree
 
OOBehaviour debugLastBehaviour
 
uint16_t entity_personality
 
NSDictionary * scriptInfo
 
NSMutableArray * subEntities
 
OOEquipmentTypemissile_list [SHIPENTITY_MAX_MISSILES]
 
OOWeakReference_primaryTarget
 
OOWeakReference_primaryAggressor
 
OOWeakReference_targetStation
 
OOWeakReference_foundTarget
 
OOWeakReference_lastEscortTarget
 
OOWeakReference_thankedShip
 
OOWeakReference_rememberedShip
 
OOWeakReference_proximityAlert
 
float reactionTime
 
HPVector trackingCurvePositions [4]
 
OOTimeAbsolute trackingCurveTimes [4]
 
HPVector trackingCurveCoeffs [3]
 
- Protected Attributes inherited from Entity
HPVector lastPosition
 
Quaternion lastOrientation
 
GLfloat distanceTravelled
 
OOMatrix rotMatrix
 
Vector velocity
 
GLfloat energy
 
GLfloat maxEnergy
 
BoundingBox boundingBox
 
GLfloat mass
 
NSMutableArray * collidingEntities
 
OOTimeAbsolute spawnTime
 
struct JSObject * _jsSelf
 
NSUInteger lastDrawCounter
 
- Protected Attributes inherited from OOWeakRefObject
OOWeakReferenceweakSelf
 

Private Attributes

OOWeakReference_subEntityTakingDamage
 
NSString * _shipKey
 
NSMutableArray * _equipment
 
float _heatInsulation
 
OOWeakReference_lastAegisLock
 
OOShipGroup_group
 
OOShipGroup_escortGroup
 
uint8_t _maxEscortCount
 
uint8_t _pendingEscortCount
 
Vector _escortPositions [MAX_ESCORTS]
 
BOOL _escortPositionsValid
 
OOWeakSet_defenseTargets
 
OOWeakSet_collisionExceptions
 
GLfloat _profileRadius
 
OOWeakReference_shipHitByLaser
 
NSString * _beaconCode
 
NSString * _beaconLabel
 
OOWeakReference_prevBeacon
 
OOWeakReference_nextBeacon
 
id< OOHUDBeaconIcon_beaconDrawable
 
double _nextAegisCheck
 
BOOL isDemoShip
 
OOScalar demoRate
 
OOTimeAbsolute demoStartTime
 
Quaternion demoStartOrientation
 

Detailed Description

Definition at line 192 of file ShipEntity.h.

Method Documentation

◆ abandonShip

- (BOOL) abandonShip

Definition at line 9589 of file ShipEntity.m.

13302{
13303 BOOL OK = NO;
13304 if ([self isPlayer] && [(PlayerEntity *)self isDocked])
13305 {
13306 OOLog(@"ShipEntity.abandonShip.failed", @"%@", @"Player cannot abandon ship while docked.");
13307 return OK;
13308 }
13309
13310 if (![self hasEscapePod])
13311 {
13312 OOLog(@"ShipEntity.abandonShip.failed", @"Ship abandonment was requested for %@, but this ship does not carry escape pod(s).", self);
13313 return OK;
13314 }
13315
13316 if (EXPECT([self launchEscapeCapsule] != NO_TARGET)) // -launchEscapeCapsule takes care of everything for the player
13317 {
13318 if (![self isPlayer])
13319 {
13320 OK = YES;
13321 // if multiple items providing escape pod, remove all of them (NPC process)
13322 while ([self hasEquipmentItemProviding:@"EQ_ESCAPE_POD"])
13323 {
13324 [self removeEquipmentItem:[self equipmentItemProviding:@"EQ_ESCAPE_POD"]];
13325 }
13326 [self setAITo:@"nullAI.plist"];
13327 behaviour = BEHAVIOUR_IDLE;
13328 frustration = 0.0;
13329 [self setScanClass: CLASS_CARGO]; // we're unmanned now!
13330 thrust = thrust * 0.5;
13331 if (thrust > 5) thrust = 5; // 5 is the thrust of an escape-capsule
13332 desired_speed = 0.0;
13333 if ([self group]) [self setGroup:nil]; // remove self from group.
13334 if (![self isSubEntity] && [self owner]) [self setOwner:nil]; //unset owner, but not if we are a subent
13335 if ([self hasEscorts])
13336 {
13337 OOShipGroup *escortGroup = [self escortGroup];
13338 NSEnumerator *escortEnum = nil;
13339 ShipEntity *escort = nil;
13340 // Note: works on escortArray rather than escortEnumerator because escorts may be mutated.
13341 for (escortEnum = [[self escortArray] objectEnumerator]; (escort = [escortEnum nextObject]); )
13342 {
13343 // act individually now!
13344 if ([escort group] == escortGroup) [escort setGroup:nil];
13345 if ([escort owner] == self) [escort setOwner:escort];
13346 }
13347
13348 // We now have no escorts.
13349 [_escortGroup release];
13350 _escortGroup = nil;
13351 }
13352 }
13353 }
13354 else if (EXPECT([self isSubEntity]))
13355 {
13356 // may still have launched passenger pods even if no crew
13357 // if multiple items providing escape pod, remove all of them (NPC process)
13358 while ([self hasEquipmentItemProviding:@"EQ_ESCAPE_POD"])
13359 {
13360 [self removeEquipmentItem:[self equipmentItemProviding:@"EQ_ESCAPE_POD"]];
13361 }
13362
13363 }
13364 else
13365 {
13366 // this shouldn't happen any more!
13367 OOLog(@"ShipEntity.abandonShip.notPossible", @"Ship %@ cannot be abandoned at this time.", self);
13368 }
13369 return OK;
13370}
#define EXPECT(x)
#define OOLog(class, format,...)
Definition OOLogging.h:88
return nil
@ NO_TARGET
Definition OOTypes.h:194
unsigned isSubEntity
Definition Entity.h:95
unsigned isPlayer
Definition Entity.h:93
id owner()
Definition Entity.m:584
BOOL hasEscorts()
GLfloat frustration
Definition ShipEntity.h:348
OOShipGroup * escortGroup()
void setGroup:(OOShipGroup *group)
OOShipGroup * group()
NSArray * escortArray()
BOOL hasEscapePod()
GLfloat thrust
Definition ShipEntity.h:246
ShipEntity * launchEscapeCapsule()
OOBehaviour behaviour
Definition ShipEntity.h:211
OOShipGroup * _escortGroup
Definition ShipEntity.h:467
GLfloat desired_speed
Definition ShipEntity.h:206
void setOwner:(Entity *who_owns_entity)

References findBoundingBoxRelativeToPosition:InVectors:i:j:, kZeroVector, vector_forward_from_quaternion(), vector_right_from_quaternion(), and vector_up_from_quaternion().

+ Here is the call graph for this function:

◆ abortDocking

- (void) abortDocking

Definition at line 9589 of file ShipEntity.m.

14037{
14038 [[UNIVERSE findEntitiesMatchingPredicate:IsStationPredicate
14039 parameter:nil
14040 inRange:-1
14041 ofEntity:nil]
14042 makeObjectsPerformSelector:@selector(abortDockingForShip:) withObject:self];
14043}

◆ absoluteIJKForSubentity

- (Triangle) absoluteIJKForSubentity

Definition at line 2092 of file ShipEntity.m.

2234{
2235 Triangle result = {{ kBasisXVector, kBasisYVector, kBasisZVector }};
2236 Entity *last = nil;
2237 Entity *father = self;
2238 OOMatrix r_mat;
2239
2240 while ((father)&&(father != last) && (father != NO_TARGET))
2241 {
2242 r_mat = [father drawRotationMatrix];
2243 result.v[0] = OOVectorMultiplyMatrix(result.v[0], r_mat);
2244 result.v[1] = OOVectorMultiplyMatrix(result.v[1], r_mat);
2245 result.v[2] = OOVectorMultiplyMatrix(result.v[2], r_mat);
2246
2247 last = father;
2248 if (![last isSubEntity]) break;
2249 father = [father owner];
2250 }
2251 return result;
2252}
Vector OOVectorMultiplyMatrix(Vector v, OOMatrix m)
Definition OOMatrix.m:129
const Vector kBasisYVector
Definition OOVector.m:30
const Vector kBasisZVector
Definition OOVector.m:31
const Vector kBasisXVector
Definition OOVector.m:29
OOMatrix drawRotationMatrix()
Definition Entity.m:880

References absoluteIJKForSubentity, Entity::absolutePositionForSubentity, doOctreesCollide(), isHitByOctree(), nil, octree, and subEntities.

Referenced by absoluteIJKForSubentity.

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ absoluteTractorPosition

- (HPVector) absoluteTractorPosition

Definition at line 14942 of file ShipEntity.m.

1541{
1542 return HPvector_add(position, vectorToHPVector(quaternion_rotate_vector([self normalOrientation], tractor_position)));
1543}
Vector quaternion_rotate_vector(Quaternion q, Vector v)
HPVector position
Definition Entity.h:112
Quaternion normalOrientation()
Definition Entity.m:739
Vector tractor_position
Definition ShipEntity.h:407

References OOEquipmentType::identifier, and nil.

+ Here is the call graph for this function:

◆ acceptAsEscort:

- (BOOL) acceptAsEscort: (ShipEntity *)  other_ship

Definition at line 9589 of file ShipEntity.m.

13701 :(ShipEntity *) other_ship
13702{
13703 // can't pair with self
13704 if (self == other_ship) return NO;
13705
13706 // no longer in flight, probably entered wormhole without telling escorts.
13707 if ([self status] != STATUS_IN_FLIGHT) return NO;
13708
13709 //increased stack depth at which it can accept escorts to avoid rejections at this stage.
13710 //doesn't seem to have any adverse effect for now. - Kaks.
13711 if ([shipAI stackDepth] > 3)
13712 {
13713 OOLog(@"ship.escort.reject", @"%@ rejecting escort %@ because AI stack depth is %llu.",self, other_ship, [shipAI stackDepth]);
13714 return NO;
13715 }
13716
13717 if ([self canAcceptEscort:other_ship])
13718 {
13719 OOShipGroup *escortGroup = [self escortGroup];
13720
13721 if ([escortGroup containsShip:other_ship]) return YES;
13722
13723 // check total number acceptable
13724 // the system's patrols don't have escorts set inside their dictionary, but accept max escorts.
13725 if (_maxEscortCount == 0 && ([self hasPrimaryRole:@"police"] || [self hasPrimaryRole:@"hunter"] || [self hasRole:@"thargoid-mothership"]))
13726 {
13728 }
13729
13730 NSUInteger maxEscorts = _maxEscortCount; // never bigger than MAX_ESCORTS.
13731 NSUInteger escortCount = [escortGroup count] - 1; // always 0 or higher.
13732
13733 if (escortCount < maxEscorts)
13734 {
13735 [other_ship setGroup:escortGroup];
13736 if ([self group] == nil)
13737 {
13738 [self setGroup:escortGroup];
13739 }
13740 else if ([self group] != escortGroup) [[self group] addShip:other_ship];
13741
13742 if (([other_ship maxFlightSpeed] < cruiseSpeed) && ([other_ship maxFlightSpeed] > cruiseSpeed * 0.3))
13743 {
13744 cruiseSpeed = [other_ship maxFlightSpeed] * 0.99;
13745 }
13746
13747 OOLog(@"ship.escort.accept", @"%@ accepting escort %@.", self, other_ship);
13748
13749 [self doScriptEvent:OOJSID("shipAcceptedEscort") withArgument:other_ship];
13750 [other_ship doScriptEvent:OOJSID("escortAccepted") withArgument:self];
13751 [shipAI message:@"ACCEPTED_ESCORT"];
13752 return YES;
13753 }
13754 else
13755 {
13756 OOLog(@"ship.escort.reject", @"%@ already got max escorts(%llu). Escort rejected: %@.", self, escortCount, other_ship);
13757 }
13758 }
13759 else
13760 {
13761 OOLog(@"ship.escort.reject", @"%@ failed canAcceptEscort for escort %@.", self, other_ship);
13762 }
13763
13764
13765 return NO;
13766}
return self
#define MAX_ESCORTS
Definition ShipEntity.h:74
OOEntityStatus status()
Definition Entity.m:794
NSUInteger count()
uint8_t _maxEscortCount
Definition ShipEntity.h:468
uint8_t escortCount()
void doScriptEvent:withArgument:(jsid message,[withArgument] id argument)
GLfloat maxFlightSpeed
Definition ShipEntity.h:239
GLfloat cruiseSpeed
Definition ShipEntity.h:243

Referenced by ShipGroupAddShip().

+ Here is the caller graph for this function:

◆ acceptDistressMessageFrom:

- (void) acceptDistressMessageFrom: (ShipEntity *)  other
implementation

Reimplemented in StationEntity.

Provided by category ShipEntity(OOAIPrivate).

Definition at line 1 of file ShipEntityAI.m.

2877 :(ShipEntity *)other
2878{
2879 [self setFoundTarget:[other primaryTarget]];
2880 if ([self isPolice])
2881 {
2882 [(ShipEntity*)[self foundTarget] markAsOffender:8 withReason:kOOLegalStatusReasonDistressCall]; // you have been warned!!
2883 }
2884
2885 NSString *context = nil;
2886#ifndef NDEBUG
2887 context = [NSString stringWithFormat:@"%@ broadcastDistressMessage", [other shortDescription]];
2888#endif
2889 [shipAI reactToMessage:@"ACCEPT_DISTRESS_CALL" context:context];
2890
2891}

◆ accuracy

- (GLfloat) accuracy

◆ activateCloakingDevice

- (BOOL) activateCloakingDevice

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12359{
12360 if (![self hasCloakingDevice] || cloaking_device_active) return cloaking_device_active; // no changes.
12361
12363 if (cloaking_device_active) [self doScriptEvent:OOJSID("shipCloakActivated")];
12365}
#define CLOAKING_DEVICE_START_ENERGY
Definition ShipEntity.h:49
GLfloat maxEnergy
Definition Entity.h:143
GLfloat energy
Definition Entity.h:142
unsigned cloaking_device_active
Definition ShipEntity.h:265
BOOL hasCloakingDevice()

◆ addCargo:

- (BOOL) addCargo: (NSArray *)  some_cargo

Definition at line 7616 of file ShipEntity.m.

8453 :(NSArray *) some_cargo
8454{
8455 if ([cargo count] + [some_cargo count] > [self maxAvailableCargoSpace])
8456 {
8457 return NO;
8458 }
8459 else
8460 {
8461 [cargo addObjectsFromArray:some_cargo];
8462 return YES;
8463 }
8464}
unsigned count
NSMutableArray * cargo
Definition ShipEntity.h:361
OOCargoQuantity maxAvailableCargoSpace()

◆ addCollisionException:

- (void) addCollisionException: (ShipEntity *)  ship

Definition at line 9589 of file ShipEntity.m.

11122 :(ShipEntity *)ship
11123{
11125 {
11126 // Allocate lazily for the benefit of the ships that never need this.
11127 _collisionExceptions = [[OOWeakSet alloc] init];
11128 }
11129 [_collisionExceptions addObject:ship];
11130}
OOWeakSet * _collisionExceptions
Definition ShipEntity.h:477

Referenced by ShipAddCollisionException().

+ Here is the caller graph for this function:

◆ addDefenseTarget:

- (BOOL) addDefenseTarget: (Entity *)  target

Definition at line 9589 of file ShipEntity.m.

11171 :(Entity *)target
11172{
11173 if ([self defenseTargetCount] >= MAX_TARGETS)
11174 {
11175 return NO;
11176 }
11177 // primary target can be a wormhole, defense targets shouldn't be
11178 if (target == nil || [self isDefenseTarget:target] || ![target isShip])
11179 {
11180 return NO;
11181 }
11182 if (_defenseTargets == nil)
11183 {
11184 // Allocate lazily for the benefit of the ships that never get in fights.
11185 _defenseTargets = [[OOWeakSet alloc] init];
11186 }
11187
11188 [_defenseTargets addObject:target];
11189 return YES;
11190}
#define MAX_TARGETS
Definition ShipEntity.h:36
unsigned isShip
Definition Entity.h:91
NSUInteger defenseTargetCount()
OOWeakSet * _defenseTargets
Definition ShipEntity.h:474

◆ addEquipmentItem:inContext:

- (BOOL) addEquipmentItem: (NSString *)  equipmentKey
inContext: (NSString *)  context 

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3529 :(NSString *)equipmentKey inContext:(NSString *)context
3530{
3531 return [self addEquipmentItem:equipmentKey withValidation:YES inContext:context];
3532}

◆ addEquipmentItem:withValidation:inContext:

- (BOOL) addEquipmentItem: (NSString *)  equipmentKey
withValidation: (BOOL)  validateAddition
inContext: (NSString *)  context 

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3535 :(NSString *)equipmentKey withValidation:(BOOL)validateAddition inContext:(NSString *)context
3536{
3537 OOEquipmentType *eqType = nil;
3538 NSString *lcEquipmentKey = [equipmentKey lowercaseString];
3539 NSString *damagedKey;
3540 BOOL isEqThargon = [lcEquipmentKey hasSuffix:@"thargon"] || [lcEquipmentKey hasPrefix:@"thargon"];
3541 BOOL isRepairedEquipment = NO;
3542
3543 if([lcEquipmentKey isEqualToString:@"thargon"]) equipmentKey = @"EQ_THARGON";
3544
3545 // canAddEquipment always checks if the undamaged version is equipped.
3546 if (validateAddition == YES && ![self canAddEquipment:equipmentKey inContext:context]) return NO;
3547
3548 if ([equipmentKey hasSuffix:@"_DAMAGED"])
3549 {
3550 eqType = [OOEquipmentType equipmentTypeWithIdentifier:[equipmentKey substringToIndex:[equipmentKey length] - [@"_DAMAGED" length]]];
3551 }
3552 else
3553 {
3554 eqType = [OOEquipmentType equipmentTypeWithIdentifier:equipmentKey];
3555 // in case we have the damaged version!
3556 if (![eqType canCarryMultiple])
3557 {
3558 damagedKey = [equipmentKey stringByAppendingString:@"_DAMAGED"];
3559 if ([_equipment containsObject:damagedKey])
3560 {
3561 [_equipment removeObject:damagedKey];
3562 isRepairedEquipment = YES;
3563 }
3564 }
3565 }
3566
3567 // does this equipment actually exist?
3568 if (eqType == nil) return NO;
3569
3570 // special cases
3571 if ([eqType isMissileOrMine] || ([self isThargoid] && isEqThargon))
3572 {
3573 if (missiles >= max_missiles) return NO;
3574
3575 missile_list[missiles] = eqType;
3576 missiles++;
3577 return YES;
3578 }
3579
3580 // don't add any thargons to non-thargoid ships.
3581 if(isEqThargon) return NO;
3582
3583 // we can theoretically add a damaged weapon, but not a working one.
3584 if([equipmentKey hasPrefix:@"EQ_WEAPON"] && ![equipmentKey hasSuffix:@"_DAMAGED"])
3585 {
3586 return NO;
3587 }
3588 // end special cases
3589
3590 if (_equipment == nil) _equipment = [[NSMutableArray alloc] init];
3591
3592 if (![equipmentKey isEqualToString:@"EQ_PASSENGER_BERTH"] && !isRepairedEquipment)
3593 {
3594 // Add to equipment_weight with all other equipment.
3595 equipment_weight += [eqType requiredCargoSpace];
3597 {
3598 // should not even happen with old save games. Reject equipment now.
3599 equipment_weight -= [eqType requiredCargoSpace];
3600 return NO;
3601 }
3602 }
3603
3604
3605 if (!isPlayer)
3606 {
3607 if ([equipmentKey isEqual:@"EQ_CARGO_BAY"])
3608 {
3610 }
3611 else if([equipmentKey isEqualToString:@"EQ_SHIELD_BOOSTER"])
3612 {
3613 maxEnergy += 256.0f;
3614 }
3615 if([equipmentKey isEqualToString:@"EQ_SHIELD_ENHANCER"])
3616 {
3617 maxEnergy += 256.0f;
3618 energy_recharge_rate *= 1.5;
3619 }
3620 }
3621 // add the equipment
3622 [_equipment addObject:equipmentKey];
3623 [self doScriptEvent:OOJSID("equipmentAdded") withArgument:equipmentKey];
3624 return YES;
3625}
OOEquipmentType * equipmentTypeWithIdentifier:(NSString *identifier)
NSMutableArray * _equipment
Definition ShipEntity.h:461
unsigned missiles
Definition ShipEntity.h:319
unsigned max_missiles
Definition ShipEntity.h:320
OOEquipmentType * missile_list[SHIPENTITY_MAX_MISSILES]
Definition ShipEntity.h:434
GLfloat energy_recharge_rate
Definition ShipEntity.h:302
OOCargoQuantity max_cargo
Definition ShipEntity.h:295
OOCargoQuantity extra_cargo
Definition ShipEntity.h:296
OOCargoQuantity equipment_weight
Definition ShipEntity.h:297
BOOL isThargoid()

Referenced by ShipAwardEquipment(), and ShipSetEquipmentStatus().

+ Here is the caller graph for this function:

◆ addFoundTargetAsDefenseTarget

- (void) addFoundTargetAsDefenseTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1152{
1153 Entity* fTarget = [self foundTarget];
1154 if (fTarget != nil)
1155 {
1156 if ([fTarget isShip] && ![(ShipEntity *)fTarget isFriendlyTo:self])
1157 {
1158 [self addDefenseTarget:fTarget];
1159 }
1160 }
1161}

◆ addFuel:

- (void) addFuel: (NSString *)  fuel_number
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2553 :(NSString*) fuel_number
2554{
2555 [self setFuel:[self fuel] + [fuel_number intValue] * 10];
2556}

◆ addImpactMoment:fraction:

- (void) addImpactMoment: (Vector)  moment
fraction: (GLfloat)  howmuch 

Definition at line 9589 of file ShipEntity.m.

12848 :(Vector) moment fraction:(GLfloat) howmuch
12849{
12850 velocity = vector_add(velocity, vector_multiply_scalar(moment, howmuch / mass));
12851}
GLfloat mass
Definition Entity.h:146
Vector velocity()

◆ addPrimaryAggressorAsDefenseTarget

- (void) addPrimaryAggressorAsDefenseTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

976{
977 Entity *primeAggressor = [self primaryAggressor];
978 if (!primeAggressor)
979 return;
980 if ([self isDefenseTarget:primeAggressor])
981 return;
982
983 if ([primeAggressor isShip] && ![(ShipEntity*)primeAggressor isFriendlyTo:self])
984 {
985 [self addDefenseTarget:primeAggressor];
986 }
987}

◆ addRole:

- (void) addRole: (NSString *)  role

Definition at line 6493 of file ShipEntity.m.

7263 :(NSString *)role
7264{
7265 [self addRole:role withProbability:0.0f];
7266}

◆ addRole:withProbability:

- (void) addRole: (NSString *)  role
withProbability: (float)  probability 

Definition at line 6493 of file ShipEntity.m.

7269 :(NSString *)role withProbability:(float)probability
7270{
7271 if (![self hasRole:role])
7272 {
7273 OORoleSet *newRoles = nil;
7274 if (roleSet != nil) newRoles = [roleSet roleSetWithAddedRole:role probability:probability];
7275 else newRoles = [OORoleSet roleSetWithRole:role probability:probability];
7276 if (newRoles != nil)
7277 {
7278 [roleSet release];
7279 roleSet = [newRoles retain];
7280 }
7281 }
7282}
instancetype roleSetWithRole:probability:(NSString *role,[probability] float probability)
Definition OORoleSet.m:50
OORoleSet * roleSet
Definition ShipEntity.h:332

◆ addSubEntity:

- (void) addSubEntity: (Entity<OOSubEntity> *)  sub
implementation

Provided by category ShipEntity(Private).

Definition at line 6493 of file ShipEntity.m.

6704 :(Entity<OOSubEntity> *)sub
6705{
6706 if (sub == nil) return;
6707
6708 if (subEntities == nil) subEntities = [[NSMutableArray alloc] init];
6709 sub->isSubEntity = YES;
6710 // Order matters - need consistent state in setOwner:. -- Ahruman 2008-04-20
6711 [subEntities addObject:sub];
6712 [sub setOwner:self];
6713
6714 [self addSubentityToCollisionRadius:sub];
6715}
void setOwner:(Entity *ent)
Definition Entity.m:577
NSMutableArray * subEntities
Definition ShipEntity.h:433

◆ addSubentityToCollisionRadius:

- (void) addSubentityToCollisionRadius: (Entity<OOSubEntity> *)  subent
implementation

Provided by category ShipEntity(Private).

Definition at line 2092 of file ShipEntity.m.

2255 :(Entity<OOSubEntity> *)subent
2256{
2257 if (!subent) return;
2258
2259 double distance = HPmagnitude([subent position]) + [subent findCollisionRadius];
2260 if ([subent isKindOfClass:[ShipEntity class]]) // Solid subentity
2261 {
2262 if (distance > collision_radius)
2263 {
2264 collision_radius = distance;
2265 }
2266
2267 mass += [subent mass];
2268 }
2269 if (distance > _profileRadius)
2270 {
2271 _profileRadius = distance;
2272 }
2273}
GLfloat collision_radius
Definition Entity.h:111
GLfloat _profileRadius
Definition ShipEntity.h:479

◆ addTarget:

- (void) addTarget: (Entity *)  targetEntity

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

10052 :(Entity *) targetEntity
10053{
10054 if (targetEntity == self) return;
10055 if (targetEntity != nil)
10056 {
10058 _primaryTarget = [targetEntity weakRetain];
10059 [self startTrackingCurve];
10060 }
10061
10062 [[self shipSubEntityEnumerator] makeObjectsPerformSelector:@selector(addTarget:) withObject:targetEntity];
10063 if (![self isSubEntity]) [self doScriptEvent:OOJSID("shipTargetAcquired") withArgument:targetEntity];
10064}
#define DESTROY(x)
Definition OOCocoa.h:75
OOWeakReference * _primaryTarget
Definition ShipEntity.h:437

◆ adjustMissedShots:

- (void) adjustMissedShots: (int delta

Definition at line 9589 of file ShipEntity.m.

12061 :(int) delta
12062{
12063 if ([self isSubEntity])
12064 {
12065 [[self owner] adjustMissedShots:delta];
12066 }
12067 else
12068 {
12069 _missed_shots += delta;
12070 if (_missed_shots < 0)
12071 {
12072 _missed_shots = 0;
12073 }
12074 }
12075}
int _missed_shots
Definition ShipEntity.h:376
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque

◆ adjustVelocity:

- (void) adjustVelocity: (Vector)  xVel

Reimplemented in StationEntity.

Definition at line 9589 of file ShipEntity.m.

12842 :(Vector) xVel
12843{
12844 velocity = vector_add(velocity, xVel);
12845}

◆ afterburnerFactor

- (float) afterburnerFactor

Definition at line 2092 of file ShipEntity.m.

4093{
4095}
GLfloat afterburner_speed_factor
Definition ShipEntity.h:292

◆ afterburnerRate

- (float) afterburnerRate

Definition at line 2092 of file ShipEntity.m.

4099{
4100 return afterburner_rate;
4101}
GLfloat afterburner_rate
Definition ShipEntity.h:291

◆ aftWeaponOffset

- (NSArray *) aftWeaponOffset

◆ ai_debugMessage:

- (void) ai_debugMessage: (NSString *)  message
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2643 :(NSString *)message
2644{
2645 NSString *desc = [NSString stringWithFormat:@"%@ %d", [self name], [self universalID]];
2646 if ([self isPlayer]) desc = @"player autopilot";
2647 OOLog(@"ai.takeAction.debugMessage", @"DEBUG: AI MESSAGE from %@: %@", desc, message);
2648}

◆ ai_throwSparks

- (void) ai_throwSparks
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2632{
2633 [self setThrowSparks:YES];
2634}

◆ alertCondition

- (OOAlertCondition) alertCondition

Reimplemented in PlayerEntity, and ProxyPlayerEntity.

Definition at line 14062 of file ShipEntity.m.

14733{
14734 if ([self status] == STATUS_DOCKED)
14735 {
14737 }
14738 if ([self hasHostileTarget] || energy < maxEnergy / 4)
14739 {
14740 return ALERT_CONDITION_RED;
14741 }
14743}
@ ALERT_CONDITION_RED
Definition ShipEntity.h:178
@ ALERT_CONDITION_YELLOW
Definition ShipEntity.h:177
@ ALERT_CONDITION_DOCKED
Definition ShipEntity.h:175
BOOL hasHostileTarget()

References SCANNER_MAX_RANGE2, and UNIVERSE.

◆ allDefenseTargets

- (NSArray *) allDefenseTargets

Definition at line 9589 of file ShipEntity.m.

11160{
11161 return [_defenseTargets allObjects];
11162}

◆ applyAttitudeChanges:

- (void) applyAttitudeChanges: (double)  delta_t

Reimplemented in PlayerEntity.

Definition at line 6493 of file ShipEntity.m.

6827 :(double) delta_t
6828{
6829 [self applyRoll:flightRoll*delta_t climb:flightPitch*delta_t andYaw:flightYaw*delta_t];
6830}

◆ applyRoll:andClimb:

- (void) applyRoll: (GLfloat)  roll1
andClimb: (GLfloat)  climb1 
implementation

Reimplemented from Entity.

Reimplemented in PlayerEntity.

Definition at line 6493 of file ShipEntity.m.

6794 :(GLfloat) roll1 andClimb:(GLfloat) climb1
6795{
6796 Quaternion q1 = kIdentityQuaternion;
6797
6798 if (!roll1 && !climb1 && !hasRotated) return;
6799
6800 if (roll1) quaternion_rotate_about_z(&q1, -roll1);
6801 if (climb1) quaternion_rotate_about_x(&q1, -climb1);
6802
6804 [self orientationChanged];
6805}
void quaternion_rotate_about_x(Quaternion *quat, OOScalar angle)
void quaternion_rotate_about_z(Quaternion *quat, OOScalar angle)
const Quaternion kIdentityQuaternion
Quaternion quaternion_multiply(Quaternion q1, Quaternion q2)
unsigned hasRotated
Definition Entity.h:97
Quaternion orientation
Definition Entity.h:114

◆ applyRoll:climb:andYaw:

- (void) applyRoll: (GLfloat)  roll1
climb: (GLfloat)  climb1
andYaw: (GLfloat)  yaw1 
implementation

Reimplemented from Entity.

Definition at line 6493 of file ShipEntity.m.

6808 :(GLfloat) roll1 climb:(GLfloat) climb1 andYaw:(GLfloat) yaw1
6809{
6810 if ((roll1 == 0.0)&&(climb1 == 0.0)&&(yaw1 == 0.0)&&(!hasRotated))
6811 return;
6812
6813 Quaternion q1 = kIdentityQuaternion;
6814
6815 if (roll1)
6816 quaternion_rotate_about_z(&q1, -roll1);
6817 if (climb1)
6818 quaternion_rotate_about_x(&q1, -climb1);
6819 if (yaw1)
6820 quaternion_rotate_about_y(&q1, -yaw1);
6821
6823 [self orientationChanged];
6824}
void quaternion_rotate_about_y(Quaternion *quat, OOScalar angle)

◆ applySticks:

- (void) applySticks: (double)  delta_t

Definition at line 7616 of file ShipEntity.m.

8140 :(double)delta_t
8141{
8142
8143 double rate1 = 2.0 * delta_t; //roll
8144 double rate2 = 4.0 * delta_t; //pitch
8145 double rate3 = 4.0 * delta_t; //yaw
8146
8147 if (((stick_roll > 0.0)&&(flightRoll < 0.0))||((stick_roll < 0.0)&&(flightRoll > 0.0)))
8148 rate1 *= 4.0; // much faster correction
8149 if (((stick_pitch > 0.0)&&(flightPitch < 0.0))||((stick_pitch < 0.0)&&(flightPitch > 0.0)))
8150 rate2 *= 4.0; // much faster correction
8151 if (((stick_yaw > 0.0)&&(flightYaw < 0.0))||((stick_yaw < 0.0)&&(flightYaw > 0.0)))
8152 rate3 *= 4.0; // much faster correction
8153
8155 {
8156 if (stick_roll == 0.0)
8157 rate1 *= 2.0; // faster correction
8158 if (stick_pitch == 0.0)
8159 rate2 *= 2.0; // faster correction
8160 if (stick_yaw == 0.0)
8161 rate3 *= 2.0; // faster correction
8162 }
8163
8164 // apply stick movement limits
8165 if (flightRoll < stick_roll - rate1)
8166 {
8167 flightRoll = flightRoll + rate1;
8168 }
8169 else if (flightRoll > stick_roll + rate1)
8170 {
8171 flightRoll = flightRoll - rate1;
8172 }
8173 else
8174 {
8176 }
8177
8178 if (flightPitch < stick_pitch - rate2)
8179 {
8180 flightPitch = flightPitch + rate2;
8181 }
8182 else if (flightPitch > stick_pitch + rate2)
8183 {
8184 flightPitch = flightPitch - rate2;
8185 }
8186 else
8187 {
8189 }
8190
8191 if (flightYaw < stick_yaw - rate3)
8192 {
8193 flightYaw = flightYaw + rate3;
8194 }
8195 else if (flightYaw > stick_yaw + rate3)
8196 {
8197 flightYaw = flightYaw - rate3;
8198 }
8199 else
8200 {
8202 }
8203
8204}
#define COMBAT_AI_TRACKS_CLOSER
Definition ShipEntity.h:131
GLfloat stick_pitch
Definition ShipEntity.h:209
GLfloat stick_yaw
Definition ShipEntity.h:210
GLfloat flightPitch
Definition ShipEntity.h:370
GLfloat accuracy
Definition ShipEntity.h:373
GLfloat stick_roll
Definition ShipEntity.h:208
GLfloat flightRoll
Definition ShipEntity.h:369
GLfloat flightYaw
Definition ShipEntity.h:371

◆ applyThrust:

- (void) applyThrust: (double)  delta_t

Definition at line 6493 of file ShipEntity.m.

6734 :(double) delta_t
6735{
6736 GLfloat dt_thrust = SHIP_THRUST_FACTOR * thrust * delta_t;
6737 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
6738 BOOL isUsingAfterburner = (canBurn && (flightSpeed > maxFlightSpeed) && (desired_speed >= flightSpeed));
6739 float max_available_speed = maxFlightSpeed;
6740 if (canBurn) max_available_speed *= [self afterburnerFactor];
6741
6742 if (thrust)
6743 {
6744 // If we have Newtonian (non-thrust) velocity, brake it.
6745 GLfloat velmag = magnitude(velocity);
6746 if (velmag)
6747 {
6748 GLfloat vscale = fmaxf((velmag - dt_thrust) / velmag, 0.0f);
6749 scale_vector(&velocity, vscale);
6750 }
6751 }
6752
6753 if (behaviour == BEHAVIOUR_TUMBLE) return;
6754
6755 // check for speed
6756 if (desired_speed > max_available_speed)
6757 desired_speed = max_available_speed;
6758
6760 {
6761 [self decrease_flight_speed: dt_thrust];
6763 }
6765 {
6766 [self increase_flight_speed: dt_thrust];
6768 }
6769 [self moveForward: delta_t*flightSpeed];
6770
6771 // burn fuel at the appropriate rate
6772 if (isUsingAfterburner) // no fuelconsumption on slowdown
6773 {
6775 while (fuel_accumulator < 0.0)
6776 {
6777 fuel--;
6778 fuel_accumulator += 1.0;
6779 }
6780 }
6781}
#define MIN_FUEL
Definition ShipEntity.h:102
#define SHIP_THRUST_FACTOR
Definition ShipEntity.h:44
GLfloat flightSpeed
Definition ShipEntity.h:368
OOFuelQuantity fuel
Definition ShipEntity.h:288
GLfloat fuel_accumulator
Definition ShipEntity.h:289

◆ approachAspectToPrimaryTarget

- (double) approachAspectToPrimaryTarget

Definition at line 9589 of file ShipEntity.m.

11252{
11253 Vector delta;
11254 Entity *target = [self primaryTarget];
11255 if (target == nil || ![target isShip]) // leave now!
11256 {
11257 return 0.0;
11258 }
11259 ShipEntity *ship_target = (ShipEntity *)target;
11260
11261 delta = HPVectorToVector(HPvector_subtract(position, target->position));
11262
11263 return dot_product(vector_normal(delta), ship_target->v_forward);
11264}
Vector v_forward
Definition ShipEntity.h:200

◆ AuthorityPredicate

+ (static BOOL) AuthorityPredicate (Entity *)  entity
(void *)  parameter 
implementation

Definition at line 14062 of file ShipEntity.m.

14063{
14064 ShipEntity *victim = parameter;
14065
14066 // Select main station, if victim is in aegis
14067 if (entity == [UNIVERSE station] && [victim withinStationAegis])
14068 {
14069 return YES;
14070 }
14071
14072 // Select police units in typical scanner range
14073 if ([entity scanClass] == CLASS_POLICE &&
14074 HPdistance2([victim position], [entity position]) < SCANNER_MAX_RANGE2)
14075 {
14076 return YES;
14077 }
14078
14079 // Reject others
14080 return NO;
14081}
#define SCANNER_MAX_RANGE2
Definition Entity.h:52
#define UNIVERSE
Definition Universe.h:842
OOScanClass scanClass()
BOOL withinStationAegis()

◆ availableCargoSpace

- (OOCargoQuantity) availableCargoSpace

Definition at line 7616 of file ShipEntity.m.

8378{
8379 // OOCargoQuantity is unsigned, we need to check for underflows.
8380 if (EXPECT_NOT([self cargoQuantityOnBoard] + equipment_weight >= max_cargo)) return 0;
8381 return [self maxAvailableCargoSpace] - [self cargoQuantityOnBoard];
8382}
#define EXPECT_NOT(x)
OOCargoQuantity cargoQuantityOnBoard()

Referenced by ShipAwardEquipment(), and ShipSetProperty().

+ Here is the caller graph for this function:

◆ avoidCollision

- (void) avoidCollision

Definition at line 6493 of file ShipEntity.m.

6834{
6835 if (scanClass == CLASS_MISSILE)
6836 return; // missiles are SUPPOSED to collide!
6837
6838 ShipEntity* prox_ship = (ShipEntity*)[self proximityAlert];
6839
6840 if (prox_ship)
6841 {
6843 {
6844 [previousCondition release];
6846 }
6847
6848 previousCondition = [[NSMutableDictionary dictionaryWithCapacity:5] retain];
6849
6850 [previousCondition oo_setInteger:behaviour forKey:@"behaviour"];
6851 if ([self primaryTarget] != nil)
6852 {
6853 // must use the weak ref here to prevent potential over-retention
6854 [previousCondition setObject:[[self primaryTarget] weakSelf] forKey:@"primaryTarget"];
6855 }
6856 [previousCondition oo_setFloat:desired_range forKey:@"desired_range"];
6857 [previousCondition oo_setFloat:desired_speed forKey:@"desired_speed"];
6858 [previousCondition oo_setHPVector:_destination forKey:@"destination"];
6859
6860 _destination = [prox_ship position];
6861 _destination = OOHPVectorInterpolate(position, [prox_ship position], 0.5); // point between us and them
6862
6864
6865 behaviour = BEHAVIOUR_AVOID_COLLISION;
6866 pitching_over = YES;
6867 }
6868}
#define PROXIMITY_AVOID_DISTANCE_FACTOR
Definition Universe.h:110
HPVector _destination
Definition ShipEntity.h:203
NSMutableDictionary * previousCondition
Definition ShipEntity.h:353
GLfloat desired_range
Definition ShipEntity.h:205
Entity * proximityAlert()
unsigned pitching_over
Definition ShipEntity.h:253

◆ ballTrackLeadingTarget:atTarget:

- (double) ballTrackLeadingTarget: (double)  delta_t
atTarget: (Entity *)  target 

Definition at line 9589 of file ShipEntity.m.

10324 :(double) delta_t atTarget:(Entity *)target
10325{
10326 if (!target)
10327 {
10328 return -2.0; // no target
10329 }
10330
10331 Vector vector_to_target;
10332 Vector axis_to_track_by;
10334 Vector my_ref = reference;
10335 double aim_cos, ref_cos;
10336 Vector leading = [target velocity];
10337
10338 // need to get vector to target in terms of this entities coordinate system
10339 HPVector my_position = [self absolutePositionForSubentity];
10340 vector_to_target = HPVectorToVector(HPvector_subtract([target position], my_position));
10341 // this is in absolute coordinates, so now rotate it
10342
10343 Entity *last = nil;
10344 Entity *father = [self parentEntity];
10345
10346 Quaternion q = kIdentityQuaternion;
10347 while ((father)&&(father != last) && (father != NO_TARGET))
10348 {
10349 /* Fix orientation */
10350 Quaternion fo = [father normalOrientation];
10351 fo.w = -fo.w;
10352 /* The below code works for player turrets where the
10353 * orientation is different, but not for NPC turrets. Taking
10354 * the normal orientation with -w works: there is probably a
10355 * neater way which someone who understands quaternions can
10356 * find, but this works well enough for 1.82 - CIM */
10357 q = quaternion_multiply(q,quaternion_conjugate(fo));
10358 last = father;
10359 if (![last isSubEntity]) break;
10360 father = [father owner];
10361 }
10362 q = quaternion_conjugate(q);
10363 // q now contains the rotation to the turret's reference system
10364
10365 vector_to_target = quaternion_rotate_vector(q,vector_to_target);
10366
10367 leading = quaternion_rotate_vector(q,leading);
10368 // rotate the vector to target and its velocity
10369
10370 if (magnitude(vector_to_target) > weaponRange * 1.01)
10371 {
10372 return -2.0; // out of range
10373 }
10374
10375 float lead = magnitude(vector_to_target) / TURRET_SHOT_SPEED;
10376
10377 vector_to_target = vector_add(vector_to_target, vector_multiply_scalar(leading, lead));
10378 vector_to_target = vector_normal_or_fallback(vector_to_target, kBasisZVector);
10379
10380 // do the tracking!
10381 aim_cos = dot_product(vector_to_target, my_aim);
10382 ref_cos = dot_product(vector_to_target, my_ref);
10383
10384
10385 if (ref_cos > TURRET_MINIMUM_COS) // target is forward of self
10386 {
10387 axis_to_track_by = cross_product(vector_to_target, my_aim);
10388 }
10389 else
10390 {
10391 return -2.0; // target is out of fire arc
10392 }
10393
10394 quaternion_rotate_about_axis(&orientation, axis_to_track_by, thrust * delta_t);
10395 [self orientationChanged];
10396
10397 [self setStatus:STATUS_ACTIVE];
10398
10399 return aim_cos;
10400}
Vector vector_forward_from_quaternion(Quaternion quat)
void quaternion_rotate_about_axis(Quaternion *quat, Vector axis, OOScalar angle)
#define TURRET_MINIMUM_COS
Definition ShipEntity.h:42
#define TURRET_SHOT_SPEED
Definition ShipEntity.h:80
Vector velocity
Definition Entity.h:140
GLfloat weaponRange
Definition ShipEntity.h:311
Vector reference
Definition ShipEntity.h:340

◆ beaconCode

- (NSString *) beaconCode
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1547{
1548 return _beaconCode;
1549}
NSString * _beaconCode
Definition ShipEntity.h:484

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ beaconDrawable

- (id< OOHUDBeaconIcon >) beaconDrawable
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1602{
1603 if (_beaconDrawable == nil)
1604 {
1605 NSString *beaconCode = [self beaconCode];
1606 NSUInteger length = [beaconCode length];
1607
1608 if (length > 1)
1609 {
1610 NSArray *iconData = [[UNIVERSE descriptions] oo_arrayForKey:beaconCode];
1611 if (iconData != nil) _beaconDrawable = [[OOPolygonSprite alloc] initWithDataArray:iconData outlineWidth:0.5 name:beaconCode];
1612 }
1613
1614 if (_beaconDrawable == nil)
1615 {
1616 if (length > 0) _beaconDrawable = [[beaconCode substringToIndex:1] retain];
1617 else _beaconDrawable = @"";
1618 }
1619 }
1620
1621 return _beaconDrawable;
1622}
NSString * beaconCode()
id< OOHUDBeaconIcon > _beaconDrawable
Definition ShipEntity.h:488

◆ beaconLabel

- (NSString *) beaconLabel
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1572{
1573 return _beaconLabel;
1574}
NSString * _beaconLabel
Definition ShipEntity.h:485

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ becomeEnergyBlast

- (void) becomeEnergyBlast

Reimplemented in StationEntity.

Definition at line 7616 of file ShipEntity.m.

9471{
9472 [UNIVERSE addEntity:[OOQuiriumCascadeEntity quiriumCascadeFromShip:self]];
9473 [self broadcastEnergyBlastImminent];
9474 [self noteKilledBy:nil damageType:kOODamageTypeCascadeWeapon];
9475 [UNIVERSE removeEntity:self];
9476}
instancetype quiriumCascadeFromShip:(ShipEntity *ship)

◆ becomeExplosion

- (void) becomeExplosion

Reimplemented in StationEntity.

Definition at line 7616 of file ShipEntity.m.

9168{
9169
9170 // check if we're destroying a subentity
9171 ShipEntity *parent = [self parentEntity];
9172 if (parent != nil)
9173 {
9174 ShipEntity *this_ship = [self retain];
9175 HPVector this_pos = [self absolutePositionForSubentity];
9176
9177 // remove this ship from its parent's subentity list
9178 [parent subEntityDied:self];
9179 [UNIVERSE addEntity:this_ship];
9180 [this_ship setPosition:this_pos];
9181 [this_ship release];
9182 if ([parent isPlayer])
9183 {
9184 // make the parent ship less reliable.
9185 [(PlayerEntity *)parent adjustTradeInFactorBy:-PLAYER_SHIP_SUBENTITY_TRADE_IN_VALUE];
9186 }
9187 }
9188
9189 HPVector xposition = position;
9190 NSUInteger i;
9191 Vector v;
9192 Quaternion q;
9193 int speed_low = 200;
9194 GLfloat n_alloys = sqrtf(sqrtf(mass / 6000.0f));
9195 NSUInteger numAlloys = 0;
9196 BOOL canReleaseSubWreckage = isWreckage && ([UNIVERSE detailLevel] >= DETAIL_LEVEL_EXTRAS);
9197
9198 if ([self status] == STATUS_DEAD)
9199 {
9200 [UNIVERSE removeEntity:self];
9201 return;
9202 }
9203 [self setStatus:STATUS_DEAD];
9204
9205 @try
9206 {
9207 if ([self isThargoid] && [roleSet hasRole:@"thargoid-mothership"]) [self broadcastThargoidDestroyed];
9208
9209 if (!suppressExplosion && ([self isVisible] || HPdistance2([self position], [PLAYER position]) < SCANNER_MAX_RANGE2))
9210 {
9211 if (!isWreckage && mass > 500000.0f && randf() < 0.25f) // big!
9212 {
9213 // draw an expanding ring
9215 [ring setVelocity:vector_multiply_scalar([self velocity], 0.25f)];
9216 [UNIVERSE addEntity:ring];
9217 }
9218
9219 BOOL add_debris = (UNIVERSE->n_entities < 0.95 * UNIVERSE_MAX_ENTITIES) &&
9220 ([UNIVERSE getTimeDelta] < 0.125); // FPS > 8
9221
9222
9223 // There are several parts to explosions, show only the main
9224 // explosion effect if UNIVERSE is almost full.
9225
9226 if (add_debris)
9227 {
9228 if ([UNIVERSE reducedDetail])
9229 {
9230 // Quick explosion effects for reduced detail mode
9231
9232 // 1. fast sparks
9233 [UNIVERSE addEntity:[OOSmallFragmentBurstEntity fragmentBurstFromEntity:self]];
9234 // 2. slow clouds
9235 [UNIVERSE addEntity:[OOBigFragmentBurstEntity fragmentBurstFromEntity:self]];
9236 // 3. flash
9237 [UNIVERSE addEntity:[OOFlashEffectEntity explosionFlashFromEntity:self]];
9238 /* This mode used to be the default for
9239 * cargo/munitions but this now must be explicitly
9240 * specified. */
9241 }
9242 else
9243 {
9244 NSString *explosionKey = @"oolite-default-ship-explosion";
9245 NSDictionary *explosion = nil;
9246 if (explosionType == nil)
9247 {
9248 explosion = [UNIVERSE explosionSetting:explosionKey];
9249 [UNIVERSE addEntity:[OOExplosionCloudEntity explosionCloudFromEntity:self withSettings:explosion]];
9250 // 3. flash
9251 [UNIVERSE addEntity:[OOFlashEffectEntity explosionFlashFromEntity:self]];
9252 }
9253 for (NSUInteger i=0;i<[explosionType count];i++)
9254 {
9255 explosionKey = [explosionType oo_stringAtIndex:i defaultValue:nil];
9256 if (explosionKey != nil)
9257 {
9258 // three special-case builtins
9259 if ([explosionKey isEqualToString:@"oolite-builtin-flash"])
9260 {
9261 [UNIVERSE addEntity:[OOFlashEffectEntity explosionFlashFromEntity:self]];
9262 }
9263 else if ([explosionKey isEqualToString:@"oolite-builtin-slowcloud"])
9264 {
9265 [UNIVERSE addEntity:[OOBigFragmentBurstEntity fragmentBurstFromEntity:self]];
9266 }
9267 else if ([explosionKey isEqualToString:@"oolite-builtin-fastspark"])
9268 {
9269 [UNIVERSE addEntity:[OOSmallFragmentBurstEntity fragmentBurstFromEntity:self]];
9270 }
9271 else
9272 {
9273 explosion = [UNIVERSE explosionSetting:explosionKey];
9274 [UNIVERSE addEntity:[OOExplosionCloudEntity explosionCloudFromEntity:self withSettings:explosion]];
9275 }
9276 }
9277 }
9278 // "fireball" explosion effect
9279
9280 }
9281 }
9282
9283 // If UNIVERSE is nearing limit for entities don't add to it!
9284 if (add_debris)
9285 {
9286 // we need to throw out cargo at this point.
9287 [self releaseCargoPodsDebris];
9288
9289 // Throw out rocks and alloys to be scooped up
9290 if ([self hasRole:@"asteroid"] || [self isBoulder])
9291 {
9292 if (!noRocks && (being_mined || randf() < 0.20))
9293 {
9294 NSString *defaultRole = @"boulder";
9295 float defaultSpeed = 50.0;
9296 if ([self isBoulder])
9297 {
9298 defaultRole = @"splinter";
9299 defaultSpeed = 20.0;
9300 if (likely_cargo == 0)
9301 {
9302 likely_cargo = 4; // compatibility with older boulders
9303 }
9304 }
9305 else if ([[self primaryAggressor] isPlayer])
9306 {
9307 [PLAYER addRoleForMining];
9308 }
9309 NSUInteger n_rocks = 2 + (Ranrot() % (likely_cargo + 1));
9310
9311 NSString *debrisRole = [[self shipInfoDictionary] oo_stringForKey:@"debris_role" defaultValue:defaultRole];
9312 for (i = 0; i < n_rocks; i++)
9313 {
9314 ShipEntity* rock = [UNIVERSE newShipWithRole:debrisRole]; // retain count = 1
9315 if (rock)
9316 {
9317 float r_speed = [rock maxFlightSpeed] > 0 ? 2.0 * [rock maxFlightSpeed] : defaultSpeed;
9318 float cr = (collision_radius < rock->collision_radius) ? collision_radius : 2 * rock->collision_radius;
9319 v.x = ((randf() * r_speed) - r_speed / 2);
9320 v.y = ((randf() * r_speed) - r_speed / 2);
9321 v.z = ((randf() * r_speed) - r_speed / 2);
9322 [rock setVelocity:vector_add(v,[self velocity])];
9323 HPVector rpos = HPvector_add(xposition,vectorToHPVector(vector_multiply_scalar(vector_normal(v),cr)));
9324 [rock setPosition:rpos];
9325
9327 [rock setOrientation:q];
9328
9329 [rock setTemperature:[self randomEjectaTemperature]];
9330 if ([self isBoulder])
9331 {
9332 [rock setScanClass: CLASS_CARGO];
9333 [rock setBounty: 0 withReason:kOOLegalStatusReasonSetup];
9334 // only make the rock have minerals if something isn't already defined for the rock
9335 if ([[rock shipInfoDictionary] oo_stringForKey:@"cargo_carried"] == nil)
9336 [rock setCommodity:@"minerals" andAmount: 1];
9337 }
9338 else
9339 {
9340 [rock setScanClass:CLASS_ROCK];
9341 [rock setIsBoulder:YES];
9342 }
9343 [UNIVERSE addEntity:rock]; // STATUS_IN_FLIGHT, AI state GLOBAL
9344 [rock release];
9345 }
9346 }
9347 }
9348 return;
9349 }
9350
9351 // throw out burning chunks of wreckage
9352 //
9353 if ((n_alloys && canFragment) || canReleaseSubWreckage)
9354 {
9355 NSUInteger n_wreckage = 0;
9356
9357 if (UNIVERSE->n_entities < 0.50 * UNIVERSE_MAX_ENTITIES)
9358 {
9359 // Create wreckage only when UNIVERSE is less than half full.
9360 // (condition set in r906 - was < 0.75 before) --Kaks 2011.10.17
9361 NSUInteger maxWrecks = 3;
9362 if (n_alloys == 0)
9363 {
9364 // must be sub-wreckage here
9365 n_wreckage = (mass > 600.0 && randf() < 0.2)?2:0;
9366 }
9367 else
9368 {
9369 n_wreckage = (n_alloys < maxWrecks)? floorf(randf()*(n_alloys+2)) : maxWrecks;
9370 }
9371 }
9372
9373 for (i = 0; i < n_wreckage; i++)
9374 {
9375 Vector r1 = [octree randomPoint];
9376 Vector dir = quaternion_rotate_vector([self normalOrientation], r1);
9377 HPVector rpos = HPvector_add(vectorToHPVector(dir), xposition);
9378 GLfloat lifetime = 750.0 * randf() + 250.0 * i + 100.0;
9379 ShipEntity *wreck = [UNIVERSE addWreckageFrom:self withRole:@"wreckage" at:rpos scale:1.0 lifetime:lifetime/2];
9380
9381 [wreck setVelocity:vector_add([wreck velocity],vector_multiply_scalar(vector_normal(dir),randf()*[wreck collisionRadius]))];
9382
9383 }
9384 n_alloys = randf() * n_alloys;
9385 }
9386 }
9387
9388 if (!canFragment)
9389 {
9390 n_alloys = 0.0;
9391 }
9392 // If UNIVERSE is almost full, don't create more than 1 piece of scrap metal.
9393 else if (!add_debris)
9394 {
9395 n_alloys = (n_alloys > 1.0) ? 1.0 : 0.0;
9396 }
9397
9398 // now convert to uint
9399 numAlloys = floorf(n_alloys);
9400
9401 // Throw out scrap metal
9402 //
9403 for (i = 0; i < numAlloys; i++)
9404 {
9405 ShipEntity* plate = [UNIVERSE newShipWithRole:@"alloy"]; // retain count = 1
9406 if (plate)
9407 {
9408 HPVector rpos = xposition;
9410 rpos.x += rrand.x; rpos.y += rrand.y; rpos.z += rrand.z;
9411 rpos.x += (ranrot_rand() % 7) - 3;
9412 rpos.y += (ranrot_rand() % 7) - 3;
9413 rpos.z += (ranrot_rand() % 7) - 3;
9414 [plate setPosition:rpos];
9415 v.x = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
9416 v.y = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
9417 v.z = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
9418 [plate setVelocity:vector_add(v,[self velocity])];
9420 [plate setOrientation:q];
9421
9422 [plate setTemperature:[self randomEjectaTemperature]];
9423 [plate setScanClass: CLASS_CARGO];
9424 [plate setCommodity:@"alloys" andAmount:1];
9425 [UNIVERSE addEntity:plate]; // STATUS_IN_FLIGHT, AI state GLOBAL
9426
9427 [plate release];
9428 }
9429 }
9430 }
9431
9432 // Explode subentities.
9433 ShipEntity *se = nil;
9434 foreach (se, [self shipSubEntityEnumerator])
9435 {
9436 [se setSuppressExplosion:suppressExplosion];
9437 [se becomeExplosion];
9438 }
9439 [self clearSubEntities];
9440
9441 // momentum from explosions
9442 if (!suppressExplosion)
9443 {
9445 [self dealMomentumWithinDesiredRange:0.125f * mass];
9446 }
9447
9448 if (self != PLAYER) // was if !isPlayer - but I think this may cause ghosts (Who's "I"? -- Ahruman)
9449 {
9450 if (isPlayer)
9451 {
9452 #ifndef NDEBUG
9453 OOLog(@"becomeExplosion.suspectedGhost.confirm", @"%@", @"Ship spotted with isPlayer set when not actually the player.");
9454 #endif
9455 isPlayer = NO;
9456 }
9457 }
9458 }
9459 @finally
9460 {
9461 if (self != PLAYER)
9462 {
9463 [UNIVERSE removeEntity:self];
9464 }
9465 }
9466}
void quaternion_set_random(Quaternion *quat)
float y
float x
@ DETAIL_LEVEL_EXTRAS
Definition OOTypes.h:247
@ UNIVERSE_MAX_ENTITIES
Definition OOTypes.h:193
Vector OORandomPositionInBoundingBox(BoundingBox bb)
Definition OOVector.m:121
#define PLAYER
void setVelocity:(Vector vel)
Definition Entity.m:758
void setOrientation:(Quaternion quat)
Definition Entity.m:726
GLfloat collisionRadius()
Definition Entity.m:906
void setScanClass:(OOScanClass sClass)
Definition Entity.m:800
BoundingBox boundingBox
Definition Entity.h:145
void setPosition:(HPVector posn)
Definition Entity.m:648
id fragmentBurstFromEntity:(Entity *entity)
instancetype explosionCloudFromEntity:withSettings:(Entity *entity,[withSettings] NSDictionary *settings)
instancetype explosionFlashFromEntity:(Entity *entity)
instancetype ringFromEntity:(Entity *sourceEntity)
id fragmentBurstFromEntity:(Entity *entity)
unsigned suppressExplosion
Definition ShipEntity.h:271
void setSuppressExplosion:(BOOL suppress)
unsigned noRocks
Definition ShipEntity.h:281
void setBounty:withReason:(OOCreditsQuantity amount,[withReason] OOLegalStatusReason reason)
NSDictionary * shipInfoDictionary()
void broadcastThargoidDestroyed()
unsigned isWreckage
Definition ShipEntity.h:269
Entity * primaryAggressor()
void subEntityDied:(ShipEntity *sub)
unsigned being_mined
Definition ShipEntity.h:257
OOCargoQuantity likely_cargo
Definition ShipEntity.h:294
NSEnumerator * shipSubEntityEnumerator()
void setTemperature:(GLfloat value)
void setIsBoulder:(BOOL flag)
BOOL isVisible()
BOOL isBoulder()
unsigned canFragment
Definition ShipEntity.h:268
void becomeExplosion()
void setCommodity:andAmount:(OOCommodityType co_type,[andAmount] OOCargoQuantity co_amount)
NSArray * explosionType
Definition ShipEntity.h:335
float randf(void)
unsigned Ranrot(void)
#define ranrot_rand()

◆ becomeLargeExplosion:

- (void) becomeLargeExplosion: (double)  factor

Reimplemented in StationEntity.

Definition at line 9589 of file ShipEntity.m.

9640 :(double)factor
9641{
9642
9643 if ([self status] == STATUS_DEAD) return;
9644 [self setStatus:STATUS_DEAD];
9645
9646 @try
9647 {
9648 // two parts to the explosion:
9649 // 1. fast sparks
9650 float how_many = factor;
9651 while (how_many > 0.5f)
9652 {
9653 [UNIVERSE addEntity:[OOSmallFragmentBurstEntity fragmentBurstFromEntity:self]];
9654 how_many -= 1.0f;
9655 }
9656 // 2. slow clouds
9657 how_many = factor;
9658 while (how_many > 0.5f)
9659 {
9660 [UNIVERSE addEntity:[OOBigFragmentBurstEntity fragmentBurstFromEntity:self]];
9661 how_many -= 1.0f;
9662 }
9663
9664 [self releaseCargoPodsDebris];
9665
9666 ShipEntity *se = nil;
9667 foreach (se, [self shipSubEntityEnumerator])
9668 {
9669 [se setSuppressExplosion:suppressExplosion];
9670 [se becomeExplosion];
9671 }
9672 [self clearSubEntities];
9673
9674 }
9675 @finally
9676 {
9677 if (!isPlayer) [UNIVERSE removeEntity:self];
9678 }
9679}

◆ becomeUncontrolledThargon

- (void) becomeUncontrolledThargon
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1744{
1745 int ent_count = UNIVERSE->n_entities;
1746 Entity** uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
1747 int i;
1748 for (i = 0; i < ent_count; i++) if (uni_entities[i]->isShip)
1749 {
1750 ShipEntity *other = (ShipEntity*)uni_entities[i];
1751 if ([other primaryTarget] == self)
1752 {
1753 [other removeTarget:self];
1754 }
1755 if ([other isDefenseTarget:self])
1756 {
1757 [other removeDefenseTarget:self];
1758 }
1759 }
1760 // now we're just a bunch of alien artefacts!
1761 scanClass = CLASS_CARGO;
1762 reportAIMessages = NO;
1763 [self setAITo:@"dumbAI.plist"];
1764 DESTROY(_primaryTarget);
1765 [self setSpeed: 0.0];
1766 [self setGroup:nil];
1767}
void removeTarget:(Entity *targetEntity)
void removeDefenseTarget:(Entity *target)

◆ behaviour

- (OOBehaviour) behaviour

◆ behaviour_attack_break_off_target:

- (void) behaviour_attack_break_off_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4368 :(double) delta_t
4369{
4370 if (![self canStillTrackPrimaryTarget])
4371 {
4372 [self noteLostTargetAndGoIdle];
4373 return;
4374 }
4375 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
4376 float max_available_speed = maxFlightSpeed;
4377 double range = [self rangeToPrimaryTarget];
4378 if (canBurn) max_available_speed *= [self afterburnerFactor];
4379
4380 desired_speed = max_available_speed;
4381
4382 Entity* target = [self primaryTarget];
4383
4385 {
4386 double target_speed = [target speed];
4387 if (desired_speed > target_speed * 3.0)
4388 {
4389 desired_speed = maxFlightSpeed; // don't overuse the injectors
4390 }
4391 }
4392
4393 if (cloakAutomatic) [self activateCloakingDevice];
4394 if ([self hasProximityAlertIgnoringTarget:NO])
4395 {
4396 [self avoidCollision];
4397 return;
4398 }
4399
4400 frustration += delta_t;
4401 if (frustration > 15.0 && accuracy >= COMBAT_AI_DOGFIGHTER && !canBurn)
4402 {
4404 }
4405 double aspect = [self approachAspectToPrimaryTarget];
4406 if (range > 3000.0 || ([target isShip] && [(ShipEntity*)target primaryTarget] != self) || frustration - floor(frustration) > fmin(1.6/max_flight_roll,aspect))
4407 {
4408 [self trackPrimaryTarget:delta_t:YES];
4409 }
4410 else
4411 {
4412// less useful at long range if not under direct fire
4413 [self evasiveAction:delta_t];
4414 }
4415
4417 {
4418 behaviour = BEHAVIOUR_ATTACK_TARGET;
4419 }
4420 else if (aspect < -0.75 && accuracy >= COMBAT_AI_DOGFIGHTER)
4421 {
4422 behaviour = BEHAVIOUR_ATTACK_SLOW_DOGFIGHT;
4423 }
4425 {
4426 frustration = 0.0;
4428 {
4429 behaviour = BEHAVIOUR_ATTACK_SLOW_DOGFIGHT;
4430 }
4431 else
4432 {
4433 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
4434 }
4435 }
4436
4437 flightYaw = 0.0;
4438}
#define COMBAT_AI_WEAPON_TEMP_READY
Definition ShipEntity.h:118
#define COMBAT_AI_DOGFIGHTER
Definition ShipEntity.h:129
#define COMBAT_OUT_RANGE_FACTOR
Definition ShipEntity.h:56
double speed()
Definition Entity.m:770
BOOL canStillTrackPrimaryTarget()
unsigned cloakAutomatic
Definition ShipEntity.h:267
GLfloat forward_weapon_temp
Definition ShipEntity.h:315
double approachAspectToPrimaryTarget()
GLfloat max_flight_roll
Definition ShipEntity.h:240

◆ behaviour_attack_broadside:

- (void) behaviour_attack_broadside: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4756 :(double) delta_t
4757{
4758 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
4759 float max_available_speed = maxFlightSpeed;
4760 double range = [self rangeToPrimaryTarget];
4761 if (canBurn) max_available_speed *= [self afterburnerFactor];
4762
4763 if (cloakAutomatic) [self activateCloakingDevice];
4764
4765 if (![self canStillTrackPrimaryTarget])
4766 {
4767 [self noteLostTargetAndGoIdle];
4768 return;
4769 }
4770
4771 desired_speed = max_available_speed;
4773 {
4774 behaviour = BEHAVIOUR_ATTACK_TARGET;
4775 }
4776 else
4777 {
4779 {
4781 {
4782 behaviour = BEHAVIOUR_ATTACK_BROADSIDE_RIGHT;
4783 [self setWeaponDataFromType:starboard_weapon_type];
4784 }
4785 else
4786 {
4787 behaviour = BEHAVIOUR_ATTACK_BROADSIDE_LEFT;
4788 [self setWeaponDataFromType:port_weapon_type];
4789 }
4790 }
4791 else
4792 {
4794 {
4795 behaviour = BEHAVIOUR_ATTACK_BROADSIDE_RIGHT;
4796 [self setWeaponDataFromType:starboard_weapon_type];
4797 }
4798 else
4799 {
4800 behaviour = BEHAVIOUR_ATTACK_BROADSIDE_LEFT;
4801 [self setWeaponDataFromType:port_weapon_type];
4802 }
4803 }
4804 jink = kZeroVector;
4805 if (weapon_damage == 0.0)
4806 { // safety in case side lasers no longer exist
4807 behaviour = BEHAVIOUR_ATTACK_TARGET;
4808 }
4809 else if (range > 0.9 * weaponRange)
4810 {
4811 behaviour = BEHAVIOUR_CLOSE_TO_BROADSIDE_RANGE;
4812 }
4813 }
4814
4815 frustration = 0.0; // behaviour changed, so reset frustration
4816
4817
4818
4819}
const Vector kZeroVector
Definition OOVector.m:28
#define COMBAT_BROADSIDE_IN_RANGE_FACTOR
Definition ShipEntity.h:55
BOOL isWeaponNone(OOWeaponType weapon)
GLfloat weapon_damage
Definition ShipEntity.h:309
Vector jink
Definition ShipEntity.h:338
GLfloat port_weapon_temp
Definition ShipEntity.h:315
GLfloat starboard_weapon_temp
Definition ShipEntity.h:315
OOWeaponType starboard_weapon_type
Definition ShipEntity.h:308
OOWeaponType port_weapon_type
Definition ShipEntity.h:307

◆ behaviour_attack_broadside_left:

- (void) behaviour_attack_broadside_left: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4822 :(double) delta_t
4823{
4824 [self behaviour_attack_broadside_target:delta_t leftside:YES];
4825}

◆ behaviour_attack_broadside_right:

- (void) behaviour_attack_broadside_right: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4828 :(double) delta_t
4829{
4830 [self behaviour_attack_broadside_target:delta_t leftside:NO];
4831}

◆ behaviour_attack_broadside_target:leftside:

- (void) behaviour_attack_broadside_target: (double)  delta_t
leftside: (BOOL)  leftside 

Definition at line 2092 of file ShipEntity.m.

4834 :(double) delta_t leftside:(BOOL) leftside
4835{
4836 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
4837 float max_available_speed = maxFlightSpeed;
4838 double range = [self rangeToPrimaryTarget];
4839 if (canBurn) max_available_speed *= [self afterburnerFactor];
4840 if ([self primaryTarget] == nil)
4841 {
4842 [self noteLostTargetAndGoIdle];
4843 return;
4844 }
4845 GLfloat currentWeaponRange = getWeaponRangeFromType(leftside?port_weapon_type:starboard_weapon_type);
4846 if (range > COMBAT_BROADSIDE_RANGE_FACTOR * currentWeaponRange)
4847 {
4848 behaviour = BEHAVIOUR_CLOSE_TO_BROADSIDE_RANGE;
4849 return;
4850 }
4851
4852// can get closer on broadsides since there's less risk of a collision
4853 if ((range < COMBAT_BROADSIDE_IN_RANGE_FACTOR * currentWeaponRange)||([self proximityAlert] != nil))
4854 {
4855 if (![self hasProximityAlertIgnoringTarget:YES])
4856 {
4857 behaviour = BEHAVIOUR_ATTACK_TARGET;
4858 }
4859 else
4860 {
4861 [self avoidCollision];
4862 return;
4863 }
4864 }
4865 else
4866 {
4867 if (![self canStillTrackPrimaryTarget])
4868 {
4869 [self noteLostTargetAndGoIdle];
4870 return;
4871 }
4872 }
4873 // control speed
4874 //
4875 BOOL isUsingAfterburner = canBurn && (flightSpeed > maxFlightSpeed);
4876 double slow_down_range = currentWeaponRange * COMBAT_WEAPON_RANGE_FACTOR * ((isUsingAfterburner)? 3.0 * [self afterburnerFactor] : 1.0);
4877// double target_speed = [target speed];
4878 if (range <= slow_down_range)
4879 desired_speed = fmin(0.8 * maxFlightSpeed, fmax((2.0-frustration)*maxFlightSpeed, 0.1 * maxFlightSpeed)); // within the weapon's range slow down to aim
4880 else
4881 desired_speed = max_available_speed; // use afterburner to approach
4882
4883 double last_success_factor = success_factor;
4884 success_factor = [self trackSideTarget:delta_t:leftside]; // do the actual piloting
4886 { // will probably have more luck with the other laser or picking a different attack method
4887 if (leftside)
4888 {
4890 {
4891 behaviour = BEHAVIOUR_ATTACK_BROADSIDE_RIGHT;
4892 }
4893 else
4894 {
4895 behaviour = BEHAVIOUR_ATTACK_TARGET;
4896 }
4897 }
4898 else
4899 {
4901 {
4902 behaviour = BEHAVIOUR_ATTACK_BROADSIDE_LEFT;
4903 }
4904 else
4905 {
4906 behaviour = BEHAVIOUR_ATTACK_TARGET;
4907 }
4908 }
4909 }
4910
4911/* FIXME: again, basically all of this next bit common with standard attack */
4912 if ((success_factor > 0.999)||(success_factor > last_success_factor))
4913 {
4914 frustration -= delta_t;
4915 if (frustration < 0.0)
4916 frustration = 0.0;
4917 }
4918 else
4919 {
4920 frustration += delta_t;
4921 if (frustration > 3.0) // 3s of frustration
4922 {
4923
4924 [self noteFrustration:@"BEHAVIOUR_ATTACK_BROADSIDE"];
4925 [self setEvasiveJink:1000.0];
4926 behaviour = BEHAVIOUR_ATTACK_FLY_FROM_TARGET;
4927 frustration = 0.0;
4929 }
4930 }
4931
4932 if (missiles) [self considerFiringMissile:delta_t];
4933
4934 if (cloakAutomatic) [self activateCloakingDevice];
4935 if (leftside)
4936 {
4937 [self firePortWeapon:range];
4938 }
4939 else
4940 {
4941 [self fireStarboardWeapon:range];
4942 }
4943
4944
4945
4947 {
4948 behaviour = BEHAVIOUR_ATTACK_TARGET;
4949 }
4950}
#define COMBAT_BROADSIDE_RANGE_FACTOR
Definition ShipEntity.h:57
#define COMBAT_AI_WEAPON_TEMP_USABLE
Definition ShipEntity.h:119
GLfloat getWeaponRangeFromType(OOWeaponType weapon_type)
#define COMBAT_WEAPON_RANGE_FACTOR
Definition ShipEntity.h:58
GLfloat weapon_temp
Definition ShipEntity.h:314
float afterburnerFactor()
GLfloat success_factor
Definition ShipEntity.h:349

◆ behaviour_attack_fly_from_target:

- (void) behaviour_attack_fly_from_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5467 :(double) delta_t
5468{
5469 double range = [self rangeToPrimaryTarget];
5470 double last_success_factor = success_factor;
5471 success_factor = range;
5472
5473 if ([self primaryTarget] == nil)
5474 {
5475 [self noteLostTargetAndGoIdle];
5476 return;
5477 }
5478 if (last_success_factor > success_factor) // our target is closing in.
5479 {
5480 frustration += delta_t;
5481 }
5482 else
5483 { // not getting away fast enough?
5484 frustration += delta_t / 4.0 ;
5485 }
5486
5487 if (frustration > 10.0)
5488 {
5489 if (randf() < 0.3) {
5490 desired_speed = maxFlightSpeed * (([self hasFuelInjection] && (fuel > MIN_FUEL)) ? [self afterburnerFactor] : 1);
5491 }
5492 else if (range > COMBAT_IN_RANGE_FACTOR * weaponRange && randf() < 0.3)
5493 {
5494 behaviour = BEHAVIOUR_ATTACK_TARGET;
5495 }
5496 GLfloat z = jink.z;
5497 if (randf() < 0.3)
5498 {
5499 z /= 2; // move the z-offset closer to the target to let him fly away from the target.
5500 desired_speed = flightSpeed * 2; // increase speed a bit.
5501 }
5502 [self setEvasiveJink:z];
5503
5504 frustration /= 2.0;
5505 }
5507 {
5508 ShipEntity* target = [self primaryTarget];
5509 double target_speed = [target speed];
5510 if (desired_speed > target_speed * 2.0)
5511 {
5512 desired_speed = maxFlightSpeed; // don't overuse the injectors
5513 }
5514 }
5515 else if (desired_speed < maxFlightSpeed * 0.5)
5516 {
5518 }
5519
5520 if (range > COMBAT_OUT_RANGE_FACTOR * weaponRange + 15.0 * jink.x ||
5521 flightSpeed > (scannerRange - range) * max_flight_pitch / 6.28)
5522 {
5523 jink = kZeroVector;
5524 behaviour = BEHAVIOUR_ATTACK_TARGET;
5525 frustration = 0.0;
5526 }
5527 [self trackPrimaryTarget:delta_t:YES];
5528
5529 if (missiles) [self considerFiringMissile:delta_t];
5530
5531 if (cloakAutomatic) [self activateCloakingDevice];
5532 if ([self hasProximityAlertIgnoringTarget:YES])
5534
5536 {
5537 double aspect = [self approachAspectToPrimaryTarget];
5538 // if we're right in their gunsights, dodge!
5539 // need to dodge sooner if in aft sights
5540 if (aspect > 0.99999 || aspect < -0.999)
5541 {
5542 frustration = 0.0;
5543 behaviour = BEHAVIOUR_EVASIVE_ACTION;
5544 }
5545 }
5546
5547}
#define COMBAT_AI_FLEES_BETTER_2
Definition ShipEntity.h:134
#define COMBAT_IN_RANGE_FACTOR
Definition ShipEntity.h:54
GLfloat max_flight_pitch
Definition ShipEntity.h:241
GLfloat scannerRange
Definition ShipEntity.h:317
void avoidCollision()

◆ behaviour_attack_fly_to_target:

- (void) behaviour_attack_fly_to_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5300 :(double) delta_t
5301{
5302 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
5303 float max_available_speed = maxFlightSpeed;
5304 double range = [self rangeToPrimaryTarget];
5305 if (canBurn) max_available_speed *= [self afterburnerFactor];
5306 if ([self primaryTarget] == nil)
5307 {
5308 [self noteLostTargetAndGoIdle];
5309 return;
5310 }
5311 Entity* rawTarget = [self primaryTarget];
5312 if (![rawTarget isShip])
5313 {
5314 // can't attack a wormhole
5315 [self noteLostTargetAndGoIdle];
5316 return;
5317 }
5318
5319 ShipEntity *target = (ShipEntity *)rawTarget;
5320 if ((range < COMBAT_IN_RANGE_FACTOR * weaponRange)||([self proximityAlert] != nil))
5321 {
5322 if (![self hasProximityAlertIgnoringTarget:YES])
5323 {
5324 behaviour = BEHAVIOUR_ATTACK_TARGET;
5325 }
5326 else
5327 {
5328 [self avoidCollision];
5329 return;
5330 }
5331 }
5332 else
5333 {
5334 if (![self canStillTrackPrimaryTarget])
5335 {
5336 [self noteLostTargetAndGoIdle];
5337 return;
5338 }
5339 }
5340
5341 // control speed
5342 //
5343 BOOL isUsingAfterburner = canBurn && (flightSpeed > maxFlightSpeed);
5344 BOOL closeQuickly = (canBurn && [target weaponRange] > weaponRange && range > weaponRange);
5345 double slow_down_range = weaponRange * COMBAT_WEAPON_RANGE_FACTOR * ((isUsingAfterburner)? 3.0 * [self afterburnerFactor] : 1.0);
5346 if (closeQuickly)
5347 {
5348 slow_down_range = weaponRange * COMBAT_OUT_RANGE_FACTOR;
5349 }
5350 double back_off_range = 10000 * COMBAT_OUT_RANGE_FACTOR * ((isUsingAfterburner)? 3.0 * [self afterburnerFactor] : 1.0);
5351 double target_speed = [target speed];
5352 double aspect = [self approachAspectToPrimaryTarget];
5353
5354 if (range <= slow_down_range)
5355 {
5356 if (range < back_off_range)
5357 {
5358 if (accuracy < COMBAT_AI_IS_SMART || ([target primaryTarget] == self && aspect > 0.8) || aim_tolerance*range > COMBAT_AI_CONFIDENCE_FACTOR)
5359 {
5360 if (accuracy >= COMBAT_AI_FLEES_BETTER && aspect > 0.8)
5361 {
5362 desired_speed = fmax(target_speed * 1.25, 0.8 * maxFlightSpeed);
5363 // stay at high speed if might be taking return fire
5364 }
5365 else
5366 {
5367 desired_speed = fmax(target_speed * 1.05, 0.25 * maxFlightSpeed); // within the weapon's range match speed
5368
5369 }
5370 }
5371 else
5372 { // smart, and not being shot at right now - slow down to attack
5373 desired_speed = fmax(0.1 * target_speed, 0.1 * maxFlightSpeed);
5374 }
5375 }
5376 else
5377 {
5378 if (accuracy < COMBAT_AI_IS_SMART || ([target isShip] && [(ShipEntity *)target primaryTarget] == self) || range > weaponRange / 2.0)
5379 {
5380 desired_speed = fmax(target_speed * 1.5, maxFlightSpeed);
5381 }
5382 else
5383 { // smart, and not being shot at right now - slow down to attack
5384 if (aspect > -0.25)
5385 {
5386 desired_speed = fmax(0.5 * target_speed, 0.5 * maxFlightSpeed);
5387 }
5388 else
5389 {
5390 desired_speed = fmax(1.25 * target_speed, 0.5 * maxFlightSpeed);
5391 }
5392 }
5393 }
5394 }
5395 else
5396 {
5397 if (closeQuickly)
5398 {
5399 desired_speed = max_available_speed; // use afterburner to approach
5400 }
5401 else
5402 {
5403 desired_speed = fmax(maxFlightSpeed,fmin(3.0 * target_speed, max_available_speed)); // possibly use afterburner to approach
5404 }
5405 }
5406
5407
5408 double last_success_factor = success_factor;
5409 success_factor = [self trackPrimaryTarget:delta_t:NO]; // do the actual piloting
5410
5411 if ((success_factor > 0.999)||(success_factor > last_success_factor))
5412 {
5413 frustration -= delta_t;
5414 if (frustration < 0.0)
5415 frustration = 0.0;
5416 }
5417 else
5418 {
5419 frustration += delta_t;
5420 if (frustration > 3.0) // 3s of frustration
5421 {
5422 [self noteFrustration:@"BEHAVIOUR_ATTACK_FLY_TO_TARGET"];
5423 [self setEvasiveJink:1000.0];
5424 behaviour = BEHAVIOUR_ATTACK_TARGET;
5425 frustration = 0.0;
5427 }
5428 }
5429
5430 if (missiles) [self considerFiringMissile:delta_t];
5431
5432 if (cloakAutomatic) [self activateCloakingDevice];
5433 [self fireMainWeapon:range];
5434
5435
5436
5438 {
5439 // don't do this if the target is fleeing and the front laser is
5440 // the only weapon, or if we're too far away to use non-front
5441 // lasers effectively
5442 if (aspect < 0 ||
5446 {
5447 frustration = 0.0;
5448 behaviour = BEHAVIOUR_ATTACK_TARGET;
5449 }
5450 }
5452 {
5453 // if we're right in their gunsights, dodge!
5454 // need to dodge sooner if in aft sights
5455 if ([target behaviour] != BEHAVIOUR_FLEE_TARGET && [target behaviour] != BEHAVIOUR_FLEE_EVASIVE_ACTION)
5456 {
5457 if ((aspect > 0.99999 && !isWeaponNone([target weaponTypeForFacing:WEAPON_FACING_FORWARD strict:NO])) || (aspect < -0.999 && !isWeaponNone([target weaponTypeForFacing:WEAPON_FACING_AFT strict:NO])))
5458 {
5459 frustration = 0.0;
5460 behaviour = BEHAVIOUR_EVASIVE_ACTION;
5461 }
5462 }
5463 }
5464}
@ WEAPON_FACING_FORWARD
Definition OOTypes.h:229
@ WEAPON_FACING_AFT
Definition OOTypes.h:230
#define COMBAT_AI_ISNT_AWFUL
Definition ShipEntity.h:123
#define COMBAT_AI_FLEES_BETTER
Definition ShipEntity.h:127
#define COMBAT_AI_CONFIDENCE_FACTOR
Definition ShipEntity.h:122
#define COMBAT_AI_IS_SMART
Definition ShipEntity.h:125
OOWeaponType aft_weapon_type
Definition ShipEntity.h:306
GLfloat aim_tolerance
Definition ShipEntity.h:375

◆ behaviour_attack_mining_target:

- (void) behaviour_attack_mining_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5259 :(double) delta_t
5260{
5261 double range = [self rangeToPrimaryTarget];
5262 if (![self canStillTrackPrimaryTarget])
5263 {
5264 [self noteLostTargetAndGoIdle];
5265 desired_speed = maxFlightSpeed * 0.375;
5266 return;
5267 }
5268 else if ((range < 650) || ([self proximityAlert] != nil))
5269 {
5270 if ([self proximityAlert] == NO_TARGET)
5271 {
5272 desired_speed = range * maxFlightSpeed / (650.0 * 16.0);
5273 }
5274 else
5275 {
5276 [self avoidCollision];
5277 }
5278 }
5279 else
5280 {
5281 //we have a target, its within scanner range, and outside 650
5282 desired_speed = maxFlightSpeed * 0.875;
5283 }
5284
5285 [self trackPrimaryTarget:delta_t:NO];
5286
5287 /* Don't open fire until within 3km - it doesn't take many mining
5288 * laser shots to destroy an asteroid, but some of these mining
5289 * ships are way too slow to effectively chase down the debris:
5290 * wait until reasonably close before trying to split it. */
5291 if (range < 3000)
5292 {
5293 [self fireMainWeapon:range];
5294 }
5295
5296
5297}

◆ behaviour_attack_slow_dogfight:

- (void) behaviour_attack_slow_dogfight: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4441 :(double) delta_t
4442{
4443 if (![self canStillTrackPrimaryTarget])
4444 {
4445 [self noteLostTargetAndGoIdle];
4446 return;
4447 }
4448 if ([self hasProximityAlertIgnoringTarget:YES])
4449 {
4450 [self avoidCollision];
4451 return;
4452 }
4453 double range = [self rangeToPrimaryTarget];
4454 ShipEntity* target = [self primaryTarget];
4455 double aspect = [self approachAspectToPrimaryTarget];
4456 if (range < 2.5*(collision_radius+target->collision_radius) && [self proximityAlert] == target && aspect > 0) {
4458 [self avoidCollision];
4459 return;
4460 }
4461 if (aspect < -0.5 && range > COMBAT_IN_RANGE_FACTOR * weaponRange * 2.0)
4462 {
4463 behaviour = BEHAVIOUR_ATTACK_TARGET;
4464 }
4465 else if (aspect < -0.5)
4466 {
4467// mostly behind target - try to stay there and keep up
4468 desired_speed = fmin(maxFlightSpeed * 0.5,[target speed]*0.5);
4469 }
4470 else if (aspect < 0.3)
4471 {
4472// to side of target - slow right down
4474 }
4475 else
4476 {
4477// coming to front of target - accelerate for a quick getaway
4478 desired_speed = maxFlightSpeed * fmin(aspect*2.5,1.0);
4479 }
4480 if (aspect > 0.85)
4481 {
4482 behaviour = BEHAVIOUR_ATTACK_BREAK_OFF_TARGET;
4483 }
4484 if (aspect > 0.0)
4485 {
4486 frustration += delta_t;
4487 }
4488 else
4489 {
4490 frustration -= delta_t;
4491 }
4492 if (frustration > 10.0)
4493 {
4494 desired_speed /= 2.0;
4495 }
4496 else if (frustration < 0.0)
4497 frustration = 0.0;
4498
4499 [self trackPrimaryTarget:delta_t:NO];
4500
4501 if (missiles) [self considerFiringMissile:delta_t];
4502
4503 if (cloakAutomatic) [self activateCloakingDevice];
4504
4505}

◆ behaviour_attack_sniper:

- (void) behaviour_attack_sniper: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5035 :(double) delta_t
5036{
5037 if (![self canStillTrackPrimaryTarget])
5038 {
5039 [self noteLostTargetAndGoIdle];
5040 return;
5041 }
5042 Entity* rawTarget = [self primaryTarget];
5043 if (![rawTarget isShip])
5044 {
5045 // can't attack a wormhole
5046 [self noteLostTargetAndGoIdle];
5047 return;
5048 }
5049 ShipEntity *target = (ShipEntity *)rawTarget;
5050
5051 double range = [self rangeToPrimaryTarget];
5052 float max_available_speed = maxFlightSpeed;
5053
5054 if (range < 15000)
5055 {
5056 behaviour = BEHAVIOUR_ATTACK_TARGET;
5057 }
5058 else
5059 {
5060 if (range > weaponRange || range > scannerRange * 0.8)
5061 {
5062 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
5063 if (canBurn && [target weaponRange] > weaponRange && range > weaponRange)
5064 {
5065 // if outside maximum weapon range, but inside target weapon range
5066 // close to fight ASAP!
5067 max_available_speed *= [self afterburnerFactor];
5068 }
5069 desired_speed = max_available_speed;
5070 }
5071 else
5072 {
5073 desired_speed = max_available_speed / 10.0f;
5074 }
5075
5076 double last_success_factor = success_factor;
5077 success_factor = [self trackPrimaryTarget:delta_t:NO];
5078
5079 if ((success_factor > 0.999)||(success_factor > last_success_factor))
5080 {
5081 frustration -= delta_t;
5082 if (frustration < 0.0)
5083 frustration = 0.0;
5084 }
5085 else
5086 {
5087 frustration += delta_t;
5088 if (frustration > 3.0) // 3s of frustration
5089 {
5090 [self noteFrustration:@"BEHAVIOUR_ATTACK_SNIPER"];
5091 [self setEvasiveJink:1000.0];
5092 behaviour = BEHAVIOUR_ATTACK_TARGET;
5093 frustration = 0.0;
5095 }
5096 }
5097
5098 }
5099
5100 if (missiles) [self considerFiringMissile:delta_t];
5101
5102 if (cloakAutomatic) [self activateCloakingDevice];
5103 [self fireMainWeapon:range];
5104
5106 {
5107 behaviour = BEHAVIOUR_ATTACK_TARGET;
5108 }
5109
5110}

◆ behaviour_attack_target:

- (void) behaviour_attack_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4557 :(double) delta_t
4558{
4559 double range = [self rangeToPrimaryTarget];
4560
4561 if (cloakAutomatic) [self activateCloakingDevice];
4562
4563/* Start of behaviour selection:
4564 * Anything beyond the basics should require accuracy >= COMBAT_AI_ISNT_AWFUL
4565 * Anything fancy should require accuracy >= COMBAT_AI_IS_SMART
4566 * If precise aim is required, behaviour should have accuracy >= COMBAT_AI_TRACKS_CLOSER
4567 * - CIM
4568 */
4569
4570 OOWeaponType forward_weapon_real_type = forward_weapon_type;
4571 GLfloat forward_weapon_real_temp = forward_weapon_temp;
4572
4573// if forward weapon is actually on a subent
4574 if (isWeaponNone(forward_weapon_real_type))
4575 {
4576 BOOL hasTurrets = NO;
4577 NSEnumerator *subEnum = [self shipSubEntityEnumerator];
4578 ShipEntity *se = nil;
4579 while (isWeaponNone(forward_weapon_real_type) && (se = [subEnum nextObject]))
4580 {
4581 forward_weapon_real_type = se->forward_weapon_type;
4582 forward_weapon_real_temp = se->forward_weapon_temp;
4583 if (se->behaviour == BEHAVIOUR_TRACK_AS_TURRET)
4584 {
4585 hasTurrets = YES;
4586 }
4587 }
4588 if (isWeaponNone(forward_weapon_real_type) && hasTurrets)
4589 { // safety for ships only equipped with turrets
4590 forward_weapon_real_type = OOWeaponTypeFromEquipmentIdentifierSloppy(@"EQ_WEAPON_PULSE_LASER");
4591 forward_weapon_real_temp = COMBAT_AI_WEAPON_TEMP_USABLE * 0.9;
4592 }
4593 }
4594
4595 if ([forward_weapon_real_type isTurretLaser])
4596 {
4597 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE;
4598 }
4599 else
4600 {
4601 BOOL in_good_range = aim_tolerance*range < COMBAT_AI_CONFIDENCE_FACTOR;
4602
4603 BOOL aft_weapon_ready = !isWeaponNone(aft_weapon_type) && (aft_weapon_temp < COMBAT_AI_WEAPON_TEMP_READY) && in_good_range;
4604 BOOL forward_weapon_ready = !isWeaponNone(forward_weapon_real_type) && (forward_weapon_real_temp < COMBAT_AI_WEAPON_TEMP_READY); // does not require in_good_range
4605 BOOL port_weapon_ready = !isWeaponNone(port_weapon_type) && (port_weapon_temp < COMBAT_AI_WEAPON_TEMP_READY) && in_good_range;
4606 BOOL starboard_weapon_ready = !isWeaponNone(starboard_weapon_type) && (starboard_weapon_temp < COMBAT_AI_WEAPON_TEMP_READY) && in_good_range;
4607// if no weapons cool enough to be good choices, be less picky
4608 BOOL weapons_heating = NO;
4609 if (!forward_weapon_ready && !aft_weapon_ready && !port_weapon_ready && !starboard_weapon_ready)
4610 {
4611 weapons_heating = YES;
4612 aft_weapon_ready = !isWeaponNone(aft_weapon_type) && (aft_weapon_temp < COMBAT_AI_WEAPON_TEMP_USABLE) && in_good_range;
4613 forward_weapon_ready = !isWeaponNone(forward_weapon_real_type) && (forward_weapon_real_temp < COMBAT_AI_WEAPON_TEMP_USABLE); // does not require in_good_range
4614 port_weapon_ready = !isWeaponNone(port_weapon_type) && (port_weapon_temp < COMBAT_AI_WEAPON_TEMP_USABLE) && in_good_range;
4615 starboard_weapon_ready = !isWeaponNone(starboard_weapon_type) && (starboard_weapon_temp < COMBAT_AI_WEAPON_TEMP_USABLE) && in_good_range;
4616 }
4617
4618 Entity* target = [self primaryTarget];
4619 double aspect = [self approachAspectToPrimaryTarget];
4620
4621 if (!forward_weapon_ready && !aft_weapon_ready && !port_weapon_ready && !starboard_weapon_ready)
4622 { // no usable weapons! Either not fitted or overheated
4623
4624 // if unarmed
4625 if (isWeaponNone(forward_weapon_real_type) &&
4629 {
4630 behaviour = BEHAVIOUR_ATTACK_FLY_FROM_TARGET;
4631 }
4632 else if (aspect > 0)
4633 {
4634 if (in_good_range)
4635 {
4636 if (accuracy >= COMBAT_AI_IS_SMART && randf() < 0.75)
4637 {
4638 behaviour = BEHAVIOUR_EVASIVE_ACTION;
4639 }
4640 else
4641 {
4642 behaviour = BEHAVIOUR_ATTACK_FLY_FROM_TARGET;
4643 }
4644 }
4645 else
4646 {
4647 // ready to get more accurate shots later
4648 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
4649 }
4650 }
4651 else
4652 {
4653 // if target is running away, stay on target
4654 // unless too close for safety
4655 if (range < COMBAT_IN_RANGE_FACTOR * weaponRange) {
4656 behaviour = BEHAVIOUR_ATTACK_FLY_FROM_TARGET;
4657 } else {
4658 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
4659 }
4660 }
4661 }
4662// if our current target isn't targeting us, and we have some idea of how to fight, and our weapons are running hot, and we're fairly nearby
4663 else if (weapons_heating && accuracy >= COMBAT_AI_ISNT_AWFUL && [target isShip] && [(ShipEntity *)target primaryTarget] != self && range < COMBAT_OUT_RANGE_FACTOR * weaponRange)
4664 {
4665// then back off a bit for weapons to cool so we get a good attack run later, rather than weaving closer
4666 float relativeSpeed = magnitude(vector_subtract([self velocity], [target velocity]));
4667 [self setEvasiveJink:(range + COMBAT_JINK_OFFSET - relativeSpeed / max_flight_pitch)];
4668 behaviour = BEHAVIOUR_ATTACK_FLY_FROM_TARGET;
4669 }
4670 else
4671 {
4674
4675
4676 if (nearby && aft_weapon_ready)
4677 {
4678 jink = kZeroVector; // almost all behaviours
4679 behaviour = BEHAVIOUR_RUNNING_DEFENSE;
4680 }
4681 else if (nearby && (port_weapon_ready || starboard_weapon_ready))
4682 {
4683 jink = kZeroVector; // almost all behaviours
4684 behaviour = BEHAVIOUR_ATTACK_BROADSIDE;
4685 }
4686 else if (nearby)
4687 {
4688 if (!pitching_over) // don't change jink in the middle of a sharp turn.
4689 {
4690 /*
4691 For most AIs, is behaviour_attack_target called as starting behaviour on every hit.
4692 Target can both fly towards or away from ourselves here. Both situations
4693 need a different jink.z for optimal collision avoidance at high speed approach and low speed dogfighting.
4694 The COMBAT_JINK_OFFSET intentionally over-compensates the range for collision radii to send ships towards
4695 the target at low speeds.
4696 */
4697 float relativeSpeed = magnitude(vector_subtract([self velocity], [target velocity]));
4698 [self setEvasiveJink:(range + COMBAT_JINK_OFFSET - relativeSpeed / max_flight_pitch)];
4699 }
4700 // good pilots use behaviour_attack_break_off_target instead
4702 {
4703 behaviour = BEHAVIOUR_ATTACK_BREAK_OFF_TARGET;
4704 }
4705 else
4706 {
4707 behaviour = BEHAVIOUR_ATTACK_FLY_FROM_TARGET;
4708 }
4709 }
4710 else if (forward_weapon_ready)
4711 {
4712 jink = kZeroVector; // almost all behaviours
4713
4714 // TODO: good pilots use behaviour_attack_sniper sometimes
4715 if (getWeaponRangeFromType(forward_weapon_real_type) > 12500 && range > 12500)
4716 {
4717 behaviour = BEHAVIOUR_ATTACK_SNIPER;
4718 }
4719// generally not good tactics the next two
4720 else if (accuracy < COMBAT_AI_ISNT_AWFUL && aspect < 0)
4721 {
4722 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX;
4723 }
4724 else if (accuracy < COMBAT_AI_ISNT_AWFUL)
4725 {
4726 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE;
4727 }
4728 else
4729 {
4730 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
4731 }
4732 }
4733 else if (port_weapon_ready || starboard_weapon_ready)
4734 {
4735 jink = kZeroVector; // almost all behaviours
4736 behaviour = BEHAVIOUR_ATTACK_BROADSIDE;
4737 }
4738 else if (aft_weapon_ready && midrange)
4739 {
4740 jink = kZeroVector; // almost all behaviours
4741 behaviour = BEHAVIOUR_RUNNING_DEFENSE;
4742 }
4743 else
4744 {
4745 jink = kZeroVector; // almost all behaviours
4746 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
4747 }
4748 }
4749 }
4750
4751 frustration = 0.0; // behaviour changed, so reset frustration
4752
4753}
OOWeaponType OOWeaponTypeFromEquipmentIdentifierSloppy(NSString *string) PURE_FUNC
GLfloat aft_weapon_temp
Definition ShipEntity.h:315
OOWeaponType forward_weapon_type
Definition ShipEntity.h:305

◆ behaviour_avoid_collision:

- (void) behaviour_avoid_collision: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5976 :(double) delta_t
5977{
5978 double distance = [self rangeToDestination];
5979 if (distance > desired_range)
5980 {
5981 [self resumePostProximityAlert];
5982 }
5983 else
5984 {
5985 ShipEntity* prox_ship = (ShipEntity*)[self proximityAlert];
5986 if (prox_ship)
5987 {
5989 _destination = prox_ship->position;
5990 }
5991 double dq = [self trackDestination:delta_t:YES]; // returns 0 when heading towards prox_ship
5992 // Heading towards target with desired_speed > 0, avoids collisions better than setting desired_speed to zero.
5993 // (tested with boa class cruiser on collisioncourse with buoy)
5994 desired_speed = maxFlightSpeed * (0.5 * dq + 0.5);
5995 }
5996
5997
5998
5999}

◆ behaviour_close_to_broadside_range:

- (void) behaviour_close_to_broadside_range: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4953 :(double) delta_t
4954{
4955 double range = [self rangeToPrimaryTarget];
4956 if ([self proximityAlert] != nil)
4957 {
4958 if ([self proximityAlert] == [self primaryTarget])
4959 {
4960 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET; // this behaviour will handle proximity_alert.
4961 [self behaviour_attack_fly_from_target: delta_t]; // do it now.
4962 }
4963 else
4964 {
4965 [self avoidCollision];
4966 }
4967 return;
4968 }
4969 if (![self canStillTrackPrimaryTarget])
4970 {
4971 [self noteLostTargetAndGoIdle];
4972 return;
4973 }
4974
4975 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE;
4976 [self behaviour_fly_to_target_six:delta_t];
4978 {
4979 [self setWeaponDataFromType:port_weapon_type];
4980 }
4981 else
4982 {
4983 [self setWeaponDataFromType:starboard_weapon_type];
4984 }
4986 {
4987 behaviour = BEHAVIOUR_ATTACK_BROADSIDE;
4988 }
4989 else
4990 {
4991 behaviour = BEHAVIOUR_CLOSE_TO_BROADSIDE_RANGE;
4992 }
4993}

◆ behaviour_close_with_target:

- (void) behaviour_close_with_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4996 :(double) delta_t
4997{
4998 double range = [self rangeToPrimaryTarget];
4999 if ([self proximityAlert] != nil)
5000 {
5001 if ([self proximityAlert] == [self primaryTarget])
5002 {
5003 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET; // this behaviour will handle proximity_alert.
5004 [self behaviour_attack_fly_from_target: delta_t]; // do it now.
5005 }
5006 else
5007 {
5008 [self avoidCollision];
5009 }
5010 return;
5011 }
5012 if (![self canStillTrackPrimaryTarget])
5013 {
5014 [self noteLostTargetAndGoIdle];
5015 return;
5016 }
5017 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE;
5018 double saved_frustration = frustration;
5019 [self behaviour_fly_to_target_six:delta_t];
5020 frustration = saved_frustration; // ignore fly-to-12 frustration
5021 frustration += delta_t;
5022 if (range <= COMBAT_IN_RANGE_FACTOR * weaponRange || frustration > 5.0)
5023 {
5024 behaviour = BEHAVIOUR_ATTACK_TARGET;
5025 }
5026 else
5027 {
5028 behaviour = BEHAVIOUR_CLOSE_WITH_TARGET;
5029 }
5030
5031
5032}

◆ behaviour_evasive_action:

- (void) behaviour_evasive_action: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4508 :(double) delta_t
4509{
4510 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
4511 float max_available_speed = maxFlightSpeed;
4512// double range = [self rangeToPrimaryTarget];
4513 if (canBurn) max_available_speed *= [self afterburnerFactor];
4514 desired_speed = max_available_speed;
4516 {
4517 ShipEntity* target = [self primaryTarget];
4518 double target_speed = [target speed];
4519 if (desired_speed > target_speed)
4520 {
4521 desired_speed = maxFlightSpeed; // don't overuse the injectors
4522 }
4523 }
4524
4525 if (cloakAutomatic) [self activateCloakingDevice];
4526 if ([self proximityAlert] != nil)
4527 {
4528 [self avoidCollision];
4529 return;
4530 }
4531
4532 [self evasiveAction:delta_t];
4533
4534 frustration += delta_t;
4535
4536 if (frustration > 0.5)
4537 {
4538 if (behaviour == BEHAVIOUR_FLEE_EVASIVE_ACTION)
4539 {
4540 [self setEvasiveJink:400.0];
4541 behaviour = BEHAVIOUR_FLEE_TARGET;
4542 }
4543 else
4544 {
4545 behaviour = BEHAVIOUR_ATTACK_TARGET;
4546 }
4547 }
4548
4549 flightYaw = 0.0;
4550
4551 // probably only useful for Thargoids, except for the occasional opportunist
4552 [self fireMainWeapon:[self rangeToPrimaryTarget]];
4553
4554}

◆ behaviour_face_destination:

- (void) behaviour_face_destination: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5696 :(double) delta_t
5697{
5698 double max_cos = MAX_COS;
5699 double distance = [self rangeToDestination];
5700 double old_pitch = flightPitch;
5701 desired_speed = 0.0;
5702 if (desired_range > 1.0 && distance > desired_range)
5703 {
5704 max_cos = sqrt(1 - 0.90 * desired_range*desired_range/(distance * distance)); // Head for a point within 95% of desired_range (must match the value in trackDestination)
5705 }
5706 double confidenceFactor = [self trackDestination:delta_t:NO];
5707 if (confidenceFactor >= max_cos && flightPitch == 0.0)
5708 {
5709 // desired facing achieved and movement stabilised.
5710 [shipAI message:@"FACING_DESTINATION"];
5711 [self doScriptEvent:OOJSID("shipNowFacingDestination")];
5712 frustration = 0.0;
5713 if(docking_match_rotation) // IDLE stops rotating while docking
5714 {
5715 behaviour = BEHAVIOUR_FLY_TO_DESTINATION;
5716 }
5717 else
5718 {
5719 behaviour = BEHAVIOUR_IDLE;
5720 }
5721 }
5722
5723 if(flightSpeed == 0) frustration += delta_t;
5724 if (frustration > 15.0 / max_flight_pitch) // allow more time for slow ships.
5725 {
5726 frustration = 0.0;
5727 [self noteFrustration:@"BEHAVIOUR_FACE_DESTINATION"];
5728 if(flightPitch == old_pitch) flightPitch = 0.5 * max_flight_pitch; // hack to get out of frustration.
5729 }
5730
5731 /* 2009-7-18 Eric: the condition check below is intended to eliminate the flippering between two positions for fast turning ships
5732 during low FPS conditions. This flippering is particular frustrating on slow computers during docking. But with my current computer I can't
5733 induce those low FPS conditions so I can't properly test if it helps.
5734 I did try with the TAF time acceleration that also generated larger frame jumps and than it seemed to help.
5735 */
5736 if(flightSpeed == 0 && frustration > 5 && confidenceFactor > 0.5 && ((flightPitch > 0 && old_pitch < 0) || (flightPitch < 0 && old_pitch > 0)))
5737 {
5738 flightPitch += 0.5 * old_pitch; // damping with last pitch value.
5739 }
5740
5741 if ([self hasProximityAlertIgnoringTarget:YES])
5742 {
5743 [self avoidCollision];
5744 }
5745
5746
5747}
#define MAX_COS
Definition ShipEntity.h:143
unsigned docking_match_rotation
Definition ShipEntity.h:251

◆ behaviour_flee_target:

- (void) behaviour_flee_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5599 :(double) delta_t
5600{
5601 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
5602 float max_available_speed = maxFlightSpeed;
5603 double range = [self rangeToPrimaryTarget];
5604 if ([self primaryTarget] == nil)
5605 {
5606 [self noteLostTargetAndGoIdle];
5607 return;
5608 }
5609 if (canBurn) max_available_speed *= [self afterburnerFactor];
5610
5611 double last_range = success_factor;
5612 success_factor = range;
5613
5614 if (range > desired_range || range == 0)
5615 [shipAI message:@"REACHED_SAFETY"];
5616 else
5617 desired_speed = max_available_speed;
5618
5619 if (range > last_range) // improvement
5620 {
5621 frustration -= 0.25 * delta_t;
5622 if (frustration < 0.0)
5623 frustration = 0.0;
5624 }
5625 else
5626 {
5627 frustration += delta_t;
5628 if (frustration > 15.0) // 15s of frustration
5629 {
5630 [self noteFrustration:@"BEHAVIOUR_FLEE_TARGET"];
5631 frustration = 0.0;
5632 }
5633 }
5634
5635 [self trackPrimaryTarget:delta_t:YES];
5636
5637 Entity *target = [self primaryTarget];
5638
5639 if (missiles && [target isShip] && [(ShipEntity *)target primaryTarget] == self)
5640 {
5641 [self considerFiringMissile:delta_t];
5642 }
5643
5644 if (([self hasCascadeMine]) && (range < 10000.0) && canBurn)
5645 {
5646 float qbomb_chance = 0.01 * delta_t;
5647 if (randf() < qbomb_chance)
5648 {
5649 [self launchCascadeMine];
5650 }
5651 }
5652
5653// thargoids won't normally be fleeing, but if they do, they can still shoot
5654 if ([forward_weapon_type isTurretLaser])
5655 {
5656 [self fireMainWeapon:range];
5657 }
5658
5659 if (cloakAutomatic) [self activateCloakingDevice];
5660
5661 // remember to look where you're going?
5662 if (accuracy >= COMBAT_AI_ISNT_AWFUL && [self hasProximityAlertIgnoringTarget:YES])
5663 {
5664 [self avoidCollision];
5665 }
5666
5667}
BOOL hasCascadeMine()

◆ behaviour_fly_from_destination:

- (void) behaviour_fly_from_destination: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5952 :(double) delta_t
5953{
5954 double distance = [self rangeToDestination];
5955 if (distance > desired_range)
5956 {
5957 // desired range achieved
5958 [shipAI message:@"DESIRED_RANGE_ACHIEVED"];
5959 [self doScriptEvent:OOJSID("shipAchievedDesiredRange")];
5960
5961 behaviour = BEHAVIOUR_IDLE;
5962 frustration = 0.0;
5963 desired_speed = 0.0;
5964 }
5965
5966 [self trackDestination:delta_t:YES];
5967 if ([self hasProximityAlertIgnoringTarget:YES])
5968 {
5969 [self avoidCollision];
5970 }
5971
5972
5973}

◆ behaviour_fly_range_from_destination:

- (void) behaviour_fly_range_from_destination: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5670 :(double) delta_t
5671{
5672 double distance = [self rangeToDestination];
5673 if (distance < desired_range)
5674 {
5675 behaviour = BEHAVIOUR_FLY_FROM_DESTINATION;
5677 {
5678 desired_speed = maxFlightSpeed; // Not all AI define speed when flying away. Start with max speed to stay compatible with such AI's, but allow faster flight if it's (e.g.) used to flee from coordinates rather than entity
5679 }
5680 }
5681 else
5682 {
5683 behaviour = BEHAVIOUR_FLY_TO_DESTINATION;
5684 }
5685 if ([self hasProximityAlertIgnoringTarget:YES])
5686 {
5687 [self avoidCollision];
5688 }
5689 frustration = 0.0;
5690
5691
5692
5693}

◆ behaviour_fly_thru_navpoints:

- (void) behaviour_fly_thru_navpoints: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

6064 :(double) delta_t
6065{
6066 int navpoint_plus_index = (next_navpoint_index + 1) % number_of_navpoints;
6067 HPVector d1 = navpoints[next_navpoint_index]; // head for this one
6068 HPVector d2 = navpoints[navpoint_plus_index]; // but be facing this one
6069
6070 HPVector rel = HPvector_between(d1, position); // vector from d1 to position
6071 HPVector ref = HPvector_between(d2, d1); // vector from d2 to d1
6072 ref = HPvector_normal(ref);
6073
6074 HPVector xp = make_HPvector(ref.y * rel.z - ref.z * rel.y, ref.z * rel.x - ref.x * rel.z, ref.x * rel.y - ref.y * rel.x);
6075
6076 GLfloat v0 = 0.0;
6077
6078 GLfloat r0 = HPdot_product(rel, ref); // proportion of rel in direction ref
6079
6080 // if r0 is negative then we're the wrong side of things
6081
6082 GLfloat r1 = HPmagnitude(xp); // distance of position from line
6083
6084 BOOL in_cone = (r0 > 0.5 * r1);
6085
6086 if (!in_cone) // are we in the approach cone ?
6087 r1 = 25.0 * flightSpeed; // aim a few km out!
6088 else
6089 r1 *= 2.0;
6090
6091 GLfloat dist2 = HPmagnitude2(rel);
6092
6093 if (dist2 < desired_range * desired_range)
6094 {
6095 // desired range achieved
6096 [self doScriptEvent:OOJSID("shipReachedNavPoint") andReactToAIMessage:@"NAVPOINT_REACHED"];
6097 if (navpoint_plus_index == 0)
6098 {
6099 [self doScriptEvent:OOJSID("shipReachedEndPoint") andReactToAIMessage:@"ENDPOINT_REACHED"];
6100 behaviour = BEHAVIOUR_IDLE;
6101 }
6102 next_navpoint_index = navpoint_plus_index; // loop as required
6103 }
6104 else
6105 {
6106 double last_success_factor = success_factor;
6107 double last_dist2 = last_success_factor;
6108 success_factor = dist2;
6109
6110 // set destination spline point from r1 and ref
6111 _destination = make_HPvector(d1.x + r1 * ref.x, d1.y + r1 * ref.y, d1.z + r1 * ref.z);
6112
6113 // do the actual piloting!!
6114 //
6115 // aim to within 1m
6116 GLfloat temp = desired_range;
6117 if (in_cone)
6118 desired_range = 1.0;
6119 else
6120 desired_range = 100.0;
6121 v0 = [self trackDestination:delta_t: NO];
6122 desired_range = temp;
6123
6124 if (dist2 < last_dist2) // improvement
6125 {
6126 frustration -= 0.25 * delta_t;
6127 if (frustration < 0.0)
6128 frustration = 0.0;
6129 }
6130 else
6131 {
6132 frustration += delta_t;
6133 if (frustration > 15.0) // 15s of frustration
6134 {
6135 [self noteFrustration:@"BEHAVIOUR_FLY_THRU_NAVPOINTS"];
6136 frustration -= 15.0; //repeat after another 15s of frustration
6137 }
6138 }
6139 }
6140
6141
6142
6143 GLfloat temp = desired_speed;
6144 desired_speed *= v0 * v0;
6145
6146 desired_speed = temp;
6147}
unsigned number_of_navpoints
Definition ShipEntity.h:420
HPVector navpoints[32]
Definition ShipEntity.h:418
unsigned next_navpoint_index
Definition ShipEntity.h:419

◆ behaviour_fly_to_destination:

- (void) behaviour_fly_to_destination: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5847 :(double) delta_t
5848{
5849 double distance = [self rangeToDestination];
5850 // double desiredRange = (dockingInstructions != nil) ? 1.2 * desired_range : desired_range; // stop a bit earlyer when docking.
5851 if (distance < desired_range) // + collision_radius)
5852 {
5853 // desired range achieved
5854 [shipAI message:@"DESIRED_RANGE_ACHIEVED"];
5855 [self doScriptEvent:OOJSID("shipAchievedDesiredRange")];
5856
5857 if(!docking_match_rotation) // IDLE stops rotating while docking
5858 {
5859 behaviour = BEHAVIOUR_IDLE;
5860 desired_speed = 0.0;
5861 }
5862 frustration = 0.0;
5863 }
5864 else
5865 {
5866 double last_distance = success_factor;
5867 success_factor = distance;
5868
5869 // do the actual piloting!!
5870 double confidenceFactor = [self trackDestination:delta_t: NO];
5871 if(confidenceFactor < 0.2) confidenceFactor = 0.2; // don't allow small or negative values.
5872
5873 /* 2009-07-19 Eric: Estimated Time of Arrival (eta) should also take the "angle to target" into account (confidenceFactor = cos(angle to target))
5874 and should not fuss about that last meter and use "distance + 1" instead of just "distance".
5875 trackDestination already did pitch regulation, use confidence here only for cutting down to high speeds.
5876 This should prevent ships crawling to their destination when they try to pull up close to their destination.
5877
5878 To prevent ships circling around their target without reaching destination I added a limitation based on turnrate,
5879 speed and distance to target. Formula based on satelite orbit:
5880 orbitspeed = turnrate (rad/sec) * radius (m) or flightSpeed = max_flight_pitch * 2 Pi * distance
5881 Speed must be significant lower when not flying in direction of target (low confidenceFactor) or it can never approach its destination
5882 and the ships runs the risk flying in circles around the target. (exclude active escorts)
5883 */
5884 GLfloat eta = ((distance + 1) - desired_range) / (0.51 * flightSpeed * confidenceFactor); // 2% safety margin assuming an average of half current speed
5885 GLfloat slowdownTime = (thrust > 0.0)? flightSpeed / (thrust) : 4.0;
5886 GLfloat minTurnSpeedFactor = 0.05 * max_flight_pitch * max_flight_roll; // faster turning implies higher speeds
5887 if (dockingInstructions != nil)
5888 {
5889 minTurnSpeedFactor /= 10.0;
5890 if (minTurnSpeedFactor * maxFlightSpeed > 20.0)
5891 {
5892 minTurnSpeedFactor /= 10.0;
5893 }
5894 }
5895
5896
5897 if (((eta < slowdownTime)&&(flightSpeed > maxFlightSpeed * minTurnSpeedFactor)) || (flightSpeed > max_flight_pitch * 5 * confidenceFactor * distance))
5898 {
5899 desired_speed = flightSpeed * 0.50; // cut speed by 50% to a minimum minTurnSpeedFactor of speed
5900 }
5901
5902 /* Flight correction block to prevent one possible form of
5903 * crashes in late docking process */
5904 if (docking_match_rotation && confidenceFactor >= MAX_COS && dockingInstructions != nil && [dockingInstructions oo_intForKey:@"docking_stage"] >= 7)
5905 {
5906 // then at this point should be rotating to match the station
5907 StationEntity* station_for_docking = (StationEntity*)[self targetStation];
5908
5909 if ((station_for_docking)&&(station_for_docking->isStation))
5910 {
5911 float rollMatch = dot_product([station_for_docking portUpVectorForShip:self],[self upVector]);
5912 if (rollMatch < MAX_COS && rollMatch > -MAX_COS)
5913 {
5914 // not matching rotating - stop until corrected
5915 desired_speed = 0.1;
5916 }
5917 else if (desired_speed <= 0.2)
5918 {
5919 // had previously paused, so return to normal speed
5920 desired_speed = [dockingInstructions oo_floatForKey:@"speed"];
5921 }
5922 }
5923 }
5924
5925
5926
5927 if (distance < last_distance) // improvement
5928 {
5929 frustration -= 0.25 * delta_t;
5930 if (frustration < 0.0)
5931 frustration = 0.0;
5932 }
5933 else
5934 {
5935 frustration += delta_t;
5936 if ((frustration > slowdownTime * 10.0 && slowdownTime > 0)||(frustration > 15.0)) // 10x slowdownTime or 15s of frustration
5937 {
5938 [self noteFrustration:@"BEHAVIOUR_FLY_TO_DESTINATION"];
5939 frustration -= slowdownTime * 5.0; //repeat after another five units of frustration
5940 }
5941 }
5942 }
5943 if ([self hasProximityAlertIgnoringTarget:YES])
5944 {
5945 [self avoidCollision];
5946 }
5947
5948
5949}
unsigned isStation
Definition Entity.h:92
Vector upVector()
NSDictionary * dockingInstructions
Definition ShipEntity.h:227
StationEntity * targetStation()

◆ behaviour_fly_to_target_six:

- (void) behaviour_fly_to_target_six: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5113 :(double) delta_t
5114{
5115 BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL);
5116 float max_available_speed = maxFlightSpeed;
5117 double range = [self rangeToPrimaryTarget];
5118 if (canBurn) max_available_speed *= [self afterburnerFactor];
5119
5120 // deal with collisions and lost targets
5121 if ([self proximityAlert] != nil)
5122 {
5123 if ([self proximityAlert] == [self primaryTarget])
5124 {
5125 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET; // this behaviour will handle proximity_alert.
5126 [self behaviour_attack_fly_from_target: delta_t]; // do it now.
5127 }
5128 else
5129 {
5130 [self avoidCollision];
5131 }
5132 return;
5133 }
5134 if (![self canStillTrackPrimaryTarget])
5135 {
5136 [self noteLostTargetAndGoIdle];
5137 return;
5138 }
5139
5140 // control speed
5141 BOOL isUsingAfterburner = canBurn && (flightSpeed > maxFlightSpeed);
5142 BOOL closeQuickly = (canBurn && range > weaponRange);
5143 double slow_down_range = weaponRange * COMBAT_WEAPON_RANGE_FACTOR * ((isUsingAfterburner)? 3.0 * [self afterburnerFactor] : 1.0);
5144 if (closeQuickly)
5145 {
5146 slow_down_range = weaponRange * COMBAT_OUT_RANGE_FACTOR;
5147 }
5148 double back_off_range = weaponRange * COMBAT_OUT_RANGE_FACTOR * ((isUsingAfterburner)? 3.0 * [self afterburnerFactor] : 1.0);
5149 Entity* rawTarget = [self primaryTarget];
5150 if (![rawTarget isShip])
5151 {
5152 [self noteLostTargetAndGoIdle];
5153 return;
5154 }
5155 ShipEntity* target = (ShipEntity *)rawTarget;
5156 double target_speed = [target speed];
5157 double last_success_factor = success_factor;
5158 double distance = [self rangeToDestination];
5159 success_factor = distance;
5160
5161 if (range < slow_down_range && (behaviour == BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX))
5162 {
5163 if (range < back_off_range)
5164 {
5165 desired_speed = fmax(0.9 * target_speed, 0.4 * maxFlightSpeed);
5166 }
5167 else
5168 {
5169 desired_speed = fmax(target_speed * 1.2, maxFlightSpeed);
5170 }
5171
5172 // avoid head-on collision
5173 if ((range < 0.5 * distance)&&(behaviour == BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX))
5174 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE;
5175 }
5176 else
5177 {
5178 if (range < back_off_range)
5179 {
5180 desired_speed = fmax(0.9 * target_speed, 0.8 * maxFlightSpeed);
5181 }
5182 else
5183 {
5184 desired_speed = max_available_speed; // use afterburner to approach
5185 }
5186 }
5187
5188
5189 // if within 0.75km of the target's six or twelve, or if target almost at standstill for 62.5% of non-thargoid ships (!),
5190 // then vector in attack.
5191 if (distance < 750.0 || (target_speed < 0.2 && ![self isThargoid] && ([self universalID] & 14) > 4))
5192 {
5193 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
5194 frustration = 0.0;
5195 desired_speed = fmax(target_speed, 0.4 * maxFlightSpeed); // within the weapon's range don't use afterburner
5196 }
5197
5198 // target-six
5199 if (behaviour == BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX)
5200 {
5201 // head for a point weapon-range * 0.5 to the six of the target
5202 //
5203 _destination = [target distance_six:0.5 * weaponRange];
5204 }
5205 // target-twelve
5206 if (behaviour == BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE)
5207 {
5208 if ([forward_weapon_type isTurretLaser])
5209 {
5210 // head for a point near the target, avoiding common Galcop weapon mount locations
5211 // TODO: this should account for weapon ranges
5212 GLfloat offset = 1000.0;
5213 GLfloat spacing = 2000.0;
5214 if (accuracy > 0.0)
5215 {
5216 offset = accuracy * 750.0;
5217 spacing = 2000.0 + (accuracy * 500.0);
5218 }
5219 if (entity_personality & 1)
5220 { // half at random
5221 offset = -offset;
5222 }
5223 _destination = [target distance_twelve:spacing withOffset:offset];
5224 }
5225 else
5226 {
5227 // head for a point 1.25km above the target
5228 _destination = [target distance_twelve:1250 withOffset:0];
5229 }
5230 }
5231
5232 pitching_over = NO; // in case it's set from elsewhere
5233 double confidenceFactor = [self trackDestination:delta_t :NO];
5234
5235 if(success_factor > last_success_factor || confidenceFactor < 0.85) frustration += delta_t;
5236 else if(frustration > 0.0) frustration -= delta_t * 0.75;
5237
5238 double aspect = [self approachAspectToPrimaryTarget];
5239 if(![forward_weapon_type isTurretLaser] && (frustration > 10 || aspect > 0.75))
5240 {
5241 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
5242 }
5243
5244 // use weaponry
5245 if (missiles) [self considerFiringMissile:delta_t];
5246
5247 if (cloakAutomatic) [self activateCloakingDevice];
5248 [self fireMainWeapon:range];
5249
5250
5251
5253 {
5254 behaviour = BEHAVIOUR_ATTACK_TARGET;
5255 }
5256}
OOUniversalID universalID
Definition Entity.h:89
HPVector distance_twelve:withOffset:(GLfloat dist,[withOffset] GLfloat offset)
uint16_t entity_personality
Definition ShipEntity.h:430
HPVector distance_six:(GLfloat dist)
voidpf uLong offset
Definition ioapi.h:140

◆ behaviour_formation_form_up:

- (void) behaviour_formation_form_up: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5794 :(double) delta_t
5795{
5796 // destination for each escort is set in update() from owner.
5797 ShipEntity* leadShip = [self owner];
5798 double distance = [self rangeToDestination];
5799 double eta = (distance - desired_range) / flightSpeed;
5800 if(eta < 0) eta = 0;
5801 if ((eta < 5.0)&&(leadShip)&&(leadShip->isShip))
5802 desired_speed = [leadShip flightSpeed] * (1 + eta * 0.05);
5803 else
5805
5806 double last_distance = success_factor;
5807 success_factor = distance;
5808
5809 // do the actual piloting!!
5810 [self trackDestination:delta_t: NO];
5811
5812 eta = eta / 0.51; // 2% safety margin assuming an average of half current speed
5813 GLfloat slowdownTime = (thrust > 0.0)? flightSpeed / (thrust) : 4.0;
5814 GLfloat minTurnSpeedFactor = 0.05 * max_flight_pitch * max_flight_roll; // faster turning implies higher speeds
5815
5816 if ((eta < slowdownTime)&&(flightSpeed > maxFlightSpeed * minTurnSpeedFactor))
5817 desired_speed = flightSpeed * 0.50; // cut speed by 50% to a minimum minTurnSpeedFactor of speed
5818
5819 if (distance < last_distance) // improvement
5820 {
5821 frustration -= 0.25 * delta_t;
5822 if (frustration < 0.0)
5823 frustration = 0.0;
5824 }
5825 else
5826 {
5827 frustration += delta_t;
5828 if (frustration > 15.0)
5829 {
5830 if (!leadShip) [self noteFrustration:@"BEHAVIOUR_FORMATION_FORM_UP"]; // escorts never reach their destination when following leader.
5831 else if (distance > 0.5 * scannerRange && !pitching_over)
5832 {
5833 pitching_over = YES; // Force the ship in a 180 degree turn. Do it here to allow escorts to break out formation for some seconds.
5834 }
5835 frustration = 0;
5836 }
5837 }
5838 if ([self hasProximityAlertIgnoringTarget:YES])
5839 {
5840 [self avoidCollision];
5841 }
5842
5843
5844}

◆ behaviour_idle:

- (void) behaviour_idle: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4150 :(double) delta_t
4151{
4152 stick_yaw = 0.0;
4153 if ((!isStation)&&(scanClass != CLASS_BUOY))
4154 {
4155 stick_roll = 0.0;
4156 }
4157 else
4158 {
4160 }
4161 if (scanClass != CLASS_BUOY)
4162 {
4163 stick_pitch = 0.0;
4164 }
4165 else
4166 {
4168 }
4169 [self applySticks:delta_t];
4170
4171
4172}

◆ behaviour_intercept_target:

- (void) behaviour_intercept_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4284 :(double) delta_t
4285{
4286 double range = [self rangeToPrimaryTarget];
4287 if (behaviour == BEHAVIOUR_INTERCEPT_TARGET)
4288 {
4290 if (range < desired_range)
4291 {
4292 [shipAI reactToMessage:@"DESIRED_RANGE_ACHIEVED" context:@"BEHAVIOUR_INTERCEPT_TARGET"];
4293 [self doScriptEvent:OOJSID("shipAchievedDesiredRange")];
4294
4295 }
4296 desired_speed = maxFlightSpeed * [self trackPrimaryTarget:delta_t:NO];
4297 }
4298 else
4299 {
4300 // = BEHAVIOUR_COLLECT_TARGET
4301 ShipEntity* target = [self primaryTarget];
4302// if somehow ended up in this state but target is not cargo, stop
4303// trying to scoop it
4304 if (!target || [target scanClass] != CLASS_CARGO || [target cargoType] == CARGO_NOT_CARGO)
4305 {
4306 [self noteLostTargetAndGoIdle];
4307 return;
4308 }
4309 double target_speed = [target speed];
4310 double eta = range / (flightSpeed - target_speed);
4311 double last_success_factor = success_factor;
4312 double last_distance = last_success_factor;
4313 double distance = [self rangeToDestination];
4314 success_factor = distance;
4315 //
4316 double slowdownTime = 96.0 / (thrust*SHIP_THRUST_FACTOR); // more thrust implies better slowing
4317 double minTurnSpeedFactor = 0.005 * max_flight_pitch * max_flight_roll; // faster turning implies higher speeds
4318
4319 if ((eta < slowdownTime)&&(flightSpeed > maxFlightSpeed * minTurnSpeedFactor))
4320 desired_speed = flightSpeed * 0.75; // cut speed by 50% to a minimum minTurnSpeedFactor of speed
4321 else
4323
4324 if (desired_speed < target_speed)
4325 {
4326 desired_speed += target_speed;
4327 if (target_speed > maxFlightSpeed)
4328 {
4329 [self noteLostTargetAndGoIdle];
4330 return;
4331 }
4332 }
4334 { // never use injectors for scooping
4336 }
4337
4338 _destination = target->position;
4339 desired_range = 0.5 * target->collision_radius;
4340 [self trackDestination: delta_t : NO];
4341
4342 //
4343 if (distance < last_distance) // improvement
4344 {
4345 frustration -= delta_t;
4346 if (frustration < 0.0)
4347 frustration = 0.0;
4348 }
4349 else
4350 {
4351 frustration += delta_t * 0.9;
4352 if (frustration > 10.0) // 10s of frustration
4353 {
4354 [self noteFrustration:@"BEHAVIOUR_INTERCEPT_TARGET"];
4355 frustration -= 5.0; //repeat after another five seconds' frustration
4356 }
4357 }
4358 }
4359 if ([self hasProximityAlertIgnoringTarget:YES])
4360 {
4361 [self avoidCollision];
4362 }
4363
4364
4365}
@ CARGO_NOT_CARGO
Definition OOTypes.h:70
OOCargoType cargoType()

◆ behaviour_land_on_planet:

- (void) behaviour_land_on_planet: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5750 :(double) delta_t
5751{
5752 double max_cos = MAX_COS2; // trackDestination returns the squared confidence in reverse mode.
5753 desired_speed = 0.0;
5754
5755 OOPlanetEntity* planet = [UNIVERSE entityForUniversalID:planetForLanding];
5756
5757 if (![planet isPlanet])
5758 {
5759 behaviour = BEHAVIOUR_IDLE;
5760 aiScriptWakeTime = 1; // reconsider JSAI
5761 [shipAI message:@"NO_PLANET_NEARBY"];
5762 return;
5763 }
5764
5765 if (HPdistance(position, [planet position]) + [self collisionRadius] < [planet radius])
5766 {
5767 // we have landed. (completely disappeared inside planet)
5768 [self landOnPlanet:planet];
5769 return;
5770 }
5771
5772 double confidenceFactor = [self trackDestination:delta_t:YES]; // turn away from destination
5773
5774 if (confidenceFactor >= max_cos && flightSpeed == 0.0)
5775 {
5776 // We are now turned away from planet. Start landing by flying backward.
5777 thrust = 0.0; // stop forward acceleration.
5778 if (magnitude2(velocity) < MAX_LANDING_SPEED2)
5779 {
5780 [self adjustVelocity:vector_multiply_scalar([self forwardVector], -max_thrust * delta_t)];
5781 }
5782 }
5783
5784
5785 if ([self hasProximityAlertIgnoringTarget:YES])
5786 {
5787 [self avoidCollision];
5788 }
5789
5790
5791}
#define MAX_COS2
Definition ShipEntity.h:144
#define MAX_LANDING_SPEED2
Definition ShipEntity.h:141
BOOL isPlanet()
Definition Entity.m:162
OOTimeAbsolute aiScriptWakeTime
Definition ShipEntity.h:224

◆ behaviour_running_defense:

- (void) behaviour_running_defense: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

5550 :(double) delta_t
5551{
5552 if (![self canStillTrackPrimaryTarget])
5553 {
5554 [self noteLostTargetAndGoIdle];
5555 return;
5556 }
5557
5558 double range = [self rangeToPrimaryTarget];
5559 desired_speed = maxFlightSpeed; // not injectors
5560 jink = kZeroVector;
5561 if (range > weaponRange || range > 0.8 * scannerRange || range == 0)
5562 {
5563 behaviour = BEHAVIOUR_CLOSE_WITH_TARGET;
5564 if ([forward_weapon_type isTurretLaser])
5565 {
5566 behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE;
5567 }
5568 frustration = 0.0;
5569 }
5570 [self trackPrimaryTarget:delta_t:YES];
5571 if ([forward_weapon_type isTurretLaser])
5572 {
5573 // most Thargoids will only have the forward weapon
5574 [self fireMainWeapon:range];
5575 }
5576 else
5577 {
5578 [self fireAftWeapon:range];
5579 }
5580 if (cloakAutomatic) [self activateCloakingDevice];
5581 if ([self hasProximityAlertIgnoringTarget:YES])
5583
5584 if (behaviour != BEHAVIOUR_CLOSE_WITH_TARGET && weapon_temp > COMBAT_AI_WEAPON_TEMP_USABLE)
5585 {
5586 behaviour = BEHAVIOUR_ATTACK_TARGET;
5587 }
5588
5589 // remember to look where you're going?
5590 if (accuracy >= COMBAT_AI_ISNT_AWFUL && [self hasProximityAlertIgnoringTarget:YES])
5591 {
5592 [self avoidCollision];
5593 }
5594
5595
5596}

◆ behaviour_scripted_ai:

- (void) behaviour_scripted_ai: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

6150 :(double) delta_t
6151{
6152
6153 JSContext *context = OOJSAcquireContext();
6154 jsval rval = JSVAL_VOID;
6155 jsval deltaJS = JSVAL_VOID;
6156 NSDictionary *result = nil;
6157
6158 BOOL OK = JS_NewNumberValue(context, delta_t, &deltaJS);
6159 if (OK)
6160 {
6161 OK = [[self script] callMethod:OOJSID("scriptedAI")
6162 inContext:context
6163 withArguments:&deltaJS
6164 count:1
6165 result:&rval];
6166 }
6167
6168 if (!OK)
6169 {
6170 OOLog(@"ai.error",@"Could not call scriptedAI in ship script of %@, reverting to idle",self);
6171 behaviour = BEHAVIOUR_IDLE;
6172 OOJSRelinquishContext(context);
6173 return;
6174 }
6175
6176 if (!JSVAL_IS_OBJECT(rval))
6177 {
6178 OOLog(@"ai.error",@"Invalid return value of scriptedAI in ship script of %@, reverting to idle",self);
6179 behaviour = BEHAVIOUR_IDLE;
6180 OOJSRelinquishContext(context);
6181 return;
6182 }
6183
6184 result = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(rval));
6185 OOJSRelinquishContext(context);
6186
6187 // roll or roll factor
6188 if ([result objectForKey:@"stickRollFactor"] != nil)
6189 {
6190 stick_roll = [result oo_floatForKey:@"stickRollFactor"] * max_flight_roll;
6191 }
6192 else
6193 {
6194 stick_roll = [result oo_floatForKey:@"stickRoll"];
6195 }
6197 {
6199 }
6200 else if (stick_roll < -max_flight_roll)
6201 {
6203 }
6204
6205 // pitch or pitch factor
6206 if ([result objectForKey:@"stickPitchFactor"] != nil)
6207 {
6208 stick_pitch = [result oo_floatForKey:@"stickPitchFactor"] * max_flight_pitch;
6209 }
6210 else
6211 {
6212 stick_pitch = [result oo_floatForKey:@"stickPitch"];
6213 }
6215 {
6217 }
6218 else if (stick_pitch < -max_flight_pitch)
6219 {
6221 }
6222
6223 // yaw or yaw factor
6224 if ([result objectForKey:@"stickYawFactor"] != nil)
6225 {
6226 stick_yaw = [result oo_floatForKey:@"stickYawFactor"] * max_flight_yaw;
6227 }
6228 else
6229 {
6230 stick_yaw = [result oo_floatForKey:@"stickYaw"];
6231 }
6233 {
6235 }
6236 else if (stick_yaw < -max_flight_yaw)
6237 {
6239 }
6240
6241 // apply sticks to current flight profile
6242 [self applySticks:delta_t];
6243
6244 // desired speed
6245 if ([result objectForKey:@"desiredSpeedFactor"] != nil)
6246 {
6247 desired_speed = [result oo_floatForKey:@"desiredSpeedFactor"] * maxFlightSpeed;
6248 }
6249 else
6250 {
6251 desired_speed = [result oo_floatForKey:@"desiredSpeed"];
6252 }
6253
6254 if (desired_speed < 0.0)
6255 {
6256 desired_speed = 0.0;
6257 }
6258 // overspeed and injector use is handled by applyThrust
6259
6260 if (behaviour == BEHAVIOUR_SCRIPTED_ATTACK_AI)
6261 {
6262 NSString* chosen_weapon = [result oo_stringForKey:@"chosenWeapon" defaultValue:@"FORWARD"];
6263 double range = [self rangeToPrimaryTarget];
6264
6265 if ([chosen_weapon isEqualToString:@"FORWARD"])
6266 {
6267 [self fireMainWeapon:range];
6268 }
6269 else if ([chosen_weapon isEqualToString:@"AFT"])
6270 {
6271 [self fireAftWeapon:range];
6272 }
6273 else if ([chosen_weapon isEqualToString:@"PORT"])
6274 {
6275 [self firePortWeapon:range];
6276 }
6277 else if ([chosen_weapon isEqualToString:@"STARBOARD"])
6278 {
6279 [self fireStarboardWeapon:range];
6280 }
6281 }
6282}
id OOJSNativeObjectFromJSObject(JSContext *context, JSObject *object)
OOINLINE JSContext * OOJSAcquireContext(void)
OOINLINE void OOJSRelinquishContext(JSContext *context)
GLfloat max_flight_yaw
Definition ShipEntity.h:242

◆ behaviour_stop_still:

- (void) behaviour_stop_still: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4138 :(double) delta_t
4139{
4140 stick_roll = 0.0;
4141 stick_pitch = 0.0;
4142 stick_yaw = 0.0;
4143 [self applySticks:delta_t];
4144
4145
4146
4147}

◆ behaviour_track_as_turret:

- (void) behaviour_track_as_turret: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

6002 :(double) delta_t
6003{
6004 double aim = -2.0;
6005 ShipEntity *turret_owner = (ShipEntity *)[self owner];
6006 ShipEntity *turret_target = (ShipEntity *)[turret_owner primaryTarget];
6007 if (turret_owner && turret_target && [turret_owner hasHostileTarget])
6008 {
6009 aim = [self ballTrackLeadingTarget:delta_t atTarget:turret_target];
6010 if (aim > -1.0) // potential target
6011 {
6012 HPVector p = HPvector_subtract([turret_target position], [turret_owner position]);
6013 double cr = [turret_owner collisionRadius];
6014
6015 if (aim > .95)
6016 {
6017 [self fireTurretCannon:HPmagnitude(p) - cr];
6018 }
6019 return;
6020 }
6021 }
6022
6023 // can't fire on primary target; track secondary targets instead
6024 NSEnumerator *targetEnum = [turret_owner defenseTargetEnumerator];
6025 Entity *target = nil;
6026 while ((target = [[targetEnum nextObject] weakRefUnderlyingObject]))
6027 {
6028 // defense targets cannot be tracked while cloaked
6029 if ([target scanClass] == CLASS_NO_DRAW || [(ShipEntity *)target isCloaked] || [target energy] <= 0.0)
6030 {
6031 [turret_owner removeDefenseTarget:target];
6032 }
6033 else
6034 {
6035 double range = [turret_owner rangeToSecondaryTarget:target];
6036 if (range < weaponRange)
6037 {
6038 aim = [self ballTrackLeadingTarget:delta_t atTarget:target];
6039 if (aim > -1.0)
6040 { // tracking...
6041 HPVector p = HPvector_subtract([target position], [turret_owner position]);
6042 double cr = [turret_owner collisionRadius];
6043
6044 if (aim > .95)
6045 { // fire!
6046 [self fireTurretCannon:HPmagnitude(p) - cr];
6047 }
6048 return;
6049 }
6050 // else that target is out of range, try the next priority defense target
6051 }
6052 else if (range > scannerRange)
6053 {
6054 [turret_owner removeDefenseTarget:target];
6055 }
6056 }
6057 }
6058
6059 // turrets now don't return to neutral facing if no suitable target
6060 // better for shooting at targets that are on edge of fire arc
6061}
double rangeToSecondaryTarget:(Entity *target)
NSEnumerator * defenseTargetEnumerator()
BOOL isCloaked()

◆ behaviour_track_target:

- (void) behaviour_track_target: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4268 :(double) delta_t
4269{
4270 if ([self primaryTarget] == nil)
4271 {
4272 [self noteLostTargetAndGoIdle];
4273 return;
4274 }
4275 [self trackPrimaryTarget:delta_t:NO]; // applies sticks
4276 if ([self hasProximityAlertIgnoringTarget:YES])
4277 {
4278 [self avoidCollision];
4279 }
4280
4281}

◆ behaviour_tractored:

- (void) behaviour_tractored: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4183 :(double) delta_t
4184{
4186 ShipEntity* hauler = (ShipEntity*)[self owner];
4187 if ((hauler)&&([hauler isShip]))
4188 {
4190 double distance = [self rangeToDestination];
4191 if (distance < desired_range)
4192 {
4193 [self performTumble];
4194 [self setStatus:STATUS_IN_FLIGHT];
4195 [hauler scoopUp:self];
4196 return;
4197 }
4198 GLfloat tf = TRACTOR_FORCE / mass;
4199 // adjust for difference in velocity (spring rule)
4200 Vector dv = vector_between([self velocity], [hauler velocity]);
4201 GLfloat moment = delta_t * 0.25 * tf;
4202 velocity.x += moment * dv.x;
4203 velocity.y += moment * dv.y;
4204 velocity.z += moment * dv.z;
4205 // acceleration = force / mass
4206 // force proportional to distance (spring rule)
4207 HPVector dp = HPvector_between(position, _destination);
4208 moment = delta_t * 0.5 * tf;
4209 velocity.x += moment * dp.x;
4210 velocity.y += moment * dp.y;
4211 velocity.z += moment * dp.z;
4212 // force inversely proportional to distance
4213 GLfloat d2 = HPmagnitude2(dp);
4214 moment = (d2 > 0.0)? delta_t * 5.0 * tf / d2 : 0.0;
4215 if (d2 > 0.0)
4216 {
4217 velocity.x += moment * dp.x;
4218 velocity.y += moment * dp.y;
4219 velocity.z += moment * dp.z;
4220 }
4221 //
4222 if ([self status] == STATUS_BEING_SCOOPED)
4223 {
4224 BOOL lost_contact = (distance > hauler->collision_radius + collision_radius + 250.0f); // 250m range for tractor beam
4225 if ([hauler isPlayer])
4226 {
4227 switch ([(PlayerEntity*)hauler dialFuelScoopStatus])
4228 {
4231 lost_contact = YES; // don't draw
4232 break;
4233
4234 case SCOOP_STATUS_OKAY:
4236 break;
4237 }
4238 }
4239
4240 if (lost_contact) // 250m range for tractor beam
4241 {
4242 // escaped tractor beam
4243 [self setStatus:STATUS_IN_FLIGHT];
4244 behaviour = BEHAVIOUR_IDLE;
4245 [self setThrust:[self maxThrust]]; // restore old thrust.
4246 frustration = 0.0;
4247 [self setOwner:self];
4248 [shipAI exitStateMachineWithMessage:nil]; // exit nullAI.plist
4249 return;
4250 }
4251 else if ([hauler isPlayer])
4252 {
4253 [(PlayerEntity*)hauler setScoopsActive];
4254 }
4255 }
4256 }
4257
4258// being tractored; sticks ignored - CIM
4259 flightYaw = 0.0;
4260
4261 desired_speed = 0.0;
4262 thrust = 25.0; // used to damp velocity (must be less than hauler thrust)
4263
4264 thrust = 0.0; // must reset thrust now
4265}
@ SCOOP_STATUS_FULL_HOLD
@ SCOOP_STATUS_NOT_INSTALLED
@ SCOOP_STATUS_ACTIVE
@ SCOOP_STATUS_OKAY
#define TRACTOR_FORCE
Definition ShipEntity.h:92
HPVector absoluteTractorPosition()
void scoopUp:(ShipEntity *other)

◆ behaviour_tumble:

- (void) behaviour_tumble: (double)  delta_t

Definition at line 2092 of file ShipEntity.m.

4175 :(double) delta_t
4176{
4177 [self applySticks:delta_t];
4178
4179
4180}

◆ bounty

- (OOCreditsQuantity) bounty

Reimplemented in PlayerEntity.

◆ broadcastAIMessage:

- (void) broadcastAIMessage: (NSString *)  ai_message

Definition at line 14062 of file ShipEntity.m.

14173 :(NSString *) ai_message
14174{
14175 NSString *expandedMessage = OOExpand(ai_message);
14176
14177 [self checkScanner];
14178 unsigned i;
14179 for (i = 0; i < n_scanned_ships ; i++)
14180 {
14181 ShipEntity* ship = scanned_ships[i];
14182 [[ship getAI] message: expandedMessage];
14183 }
14184}
#define OOExpand(string,...)
void message:(NSString *ms)
Definition AI.m:600
ShipEntity * scanned_ships[MAX_SCAN_NUMBER+1]
Definition ShipEntity.h:413
unsigned n_scanned_ships
Definition ShipEntity.h:415

◆ broadcastDistressMessage

- (void) broadcastDistressMessage

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

761{
762 /*-- Locates all the stations, bounty hunters and police ships in range and tells them that you are under attack --*/
763 [self broadcastDistressMessageWithDumping:YES];
764}

◆ broadcastDistressMessageWithDumping:

- (void) broadcastDistressMessageWithDumping: (BOOL)  dumpCargo

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

766 :(BOOL)dumpCargo
767{
768 [self checkScannerIgnoringUnpowered];
769 DESTROY(_foundTarget);
770
771 ShipEntity *aggressor_ship = (ShipEntity*)[self primaryAggressor];
772 if (aggressor_ship == nil) return;
773
774 // don't send too many distress messages at once, space them out semi-randomly
775 if (messageTime > 2.0 * randf()) return;
776
777 NSString *distress_message = nil;
778 BOOL is_buoy = (scanClass == CLASS_BUOY);
779 if (is_buoy) distress_message = @"[buoy-distress-call]";
780 else distress_message = @"[distress-call]";
781
782 unsigned i;
783 for (i = 0; i < n_scanned_ships; i++)
784 {
785 ShipEntity* ship = scanned_ships[i];
786
787 // dump cargo if energy is low
788 if (dumpCargo && !is_buoy && [self primaryAggressor] == ship && energy < 0.375 * maxEnergy)
789 {
790 [self ejectCargo];
791 [self performFlee];
792 }
793
794 // tell it! (only plist AIs send comms here; JS AIs are
795 // expected to handle their own)
796 if (ship->isPlayer && ![self hasNewAI])
797 {
798 [ship doScriptEvent:OOJSID("distressMessageReceived") withArgument:aggressor_ship andArgument:self];
799
800 if (!is_buoy && [self primaryAggressor] == ship && energy < 0.375 * maxEnergy)
801 {
802 [self sendExpandedMessage:@"[beg-for-mercy]" toShip:ship];
803 }
804 else if ([self bounty] == 0)
805 {
806 // only send distress message to player if plausibly sending
807 // one more generally
808 [self sendExpandedMessage:distress_message toShip:ship];
809 }
810
811 // reset the thanked_ship_id
812 DESTROY(_thankedShip);
813 }
814 else if ([self bounty] == 0 && [ship crew]) // Only clean ships can have their distress calls accepted
815 {
816 [ship doScriptEvent:OOJSID("distressMessageReceived") withArgument:aggressor_ship andArgument:self];
817
818 // we only can send distressMessages to ships that are known to have a "ACCEPT_DISTRESS_CALL" reaction
819 // in their AI, or they might react wrong on the added found_target.
820
821 // ship must have a plist AI for this next bit. JS AIs
822 // should already have done something sensible on
823 // distressMessageReceived
824 if (![self hasNewAI])
825 {
826 // FIXME: this test only works with core AIs
827 if (ship->isStation || [ship hasPrimaryRole:@"police"] || [ship hasPrimaryRole:@"hunter"])
828 {
829 [ship acceptDistressMessageFrom:self];
830 }
831 }
832 }
833 }
834}
void acceptDistressMessageFrom:(ShipEntity *other)
void doScriptEvent:withArgument:andArgument:(jsid message,[withArgument] id argument1,[andArgument] id argument2)

◆ broadcastEnergyBlastImminent

- (void) broadcastEnergyBlastImminent

Definition at line 7616 of file ShipEntity.m.

9481{
9482 // anyone further away than typical scanner range probably doesn't need to hear
9483 NSArray* targets = [UNIVERSE entitiesWithinRange:SCANNER_MAX_RANGE ofEntity:self];
9484 if ([targets count] > 0)
9485 {
9486 unsigned i;
9487 for (i = 0; i < [targets count]; i++)
9488 {
9489 Entity *e2 = [targets objectAtIndex:i];
9490 if ([e2 isShip])
9491 {
9492 ShipEntity *se = (ShipEntity *)e2;
9493 [se setFoundTarget:self];
9494 [se reactToAIMessage:@"CASCADE_WEAPON_DETECTED" context:@"nearby Q-mine"];
9495 [se doScriptEvent:OOJSID("cascadeWeaponDetected") withArgument:self];
9496 }
9497 }
9498 }
9499}
void reactToAIMessage:context:(NSString *message,[context] NSString *debugContext)
void setFoundTarget:(Entity *targetEntity)

◆ broadcastHitByLaserFrom:

- (void) broadcastHitByLaserFrom: (ShipEntity*)  aggressor_ship

Definition at line 14062 of file ShipEntity.m.

14084 :(ShipEntity *) aggressor_ship
14085{
14086 /*-- If you're clean, locates all police and stations in range and tells them OFFENCE_COMMITTED --*/
14087 if (!UNIVERSE) return;
14088 if ([self bounty]) return;
14089 if (!aggressor_ship) return;
14090
14091 if ( (scanClass == CLASS_NEUTRAL)||
14092 (scanClass == CLASS_STATION)||
14093 (scanClass == CLASS_BUOY)||
14094 (scanClass == CLASS_POLICE)||
14095 (scanClass == CLASS_MILITARY)||
14096 (scanClass == CLASS_PLAYER)) // only for active ships...
14097 {
14098 NSArray *authorities = nil;
14099 ShipEntity *auth = nil;
14100
14101 authorities = [UNIVERSE findShipsMatchingPredicate:AuthorityPredicate
14102 parameter:self
14103 inRange:-1
14104 ofEntity:nil];
14105 foreach (auth, authorities)
14106 {
14107 [auth setFoundTarget:aggressor_ship];
14108 [auth doScriptEvent:OOJSID("offenceCommittedNearby") withArgument:aggressor_ship andArgument:self];
14109 [auth reactToAIMessage:@"OFFENCE_COMMITTED" context:@"combat update"];
14110 }
14111 }
14112}
OOCreditsQuantity bounty
Definition ShipEntity.h:300

◆ broadcastMessage:withUnpilotedOverride:

- (void) broadcastMessage: (NSString *)  message_text
withUnpilotedOverride: (BOOL)  unpilotedOverride 

Definition at line 14062 of file ShipEntity.m.

14187 :(NSString *) message_text withUnpilotedOverride:(BOOL) unpilotedOverride
14188{
14189 NSString *expandedMessage = OOExpand(message_text); // consistent with broadcast message.
14190
14191
14192 if (!crew && !unpilotedOverride)
14193 return; // nobody to send the signal and no override for unpiloted craft is set
14194
14195 [self checkScanner];
14196 unsigned i;
14197 for (i = 0; i < n_scanned_ships ; i++)
14198 {
14199 ShipEntity* ship = scanned_ships[i];
14200 if (![ship isPlayer]) [ship receiveCommsMessage:expandedMessage from:self];
14201 }
14202
14203 PlayerEntity *player = PLAYER; // make sure that the player always receives a message when in range
14204 // SCANNER_MAX_RANGE2 because it's the player's scanner range
14205 // which is important
14206 if (HPdistance2(position, [player position]) < SCANNER_MAX_RANGE2)
14207 {
14208 [self setCommsMessageColor];
14209 [player receiveCommsMessage:expandedMessage from:self];
14210 messageTime = 6.0;
14211 [UNIVERSE resetCommsLogColor];
14212 }
14213}
void receiveCommsMessage:from:(NSString *message_text, [from] ShipEntity *other)
double messageTime
Definition ShipEntity.h:382
NSArray * crew
Definition ShipEntity.h:399

◆ broadcastThargoidDestroyed

- (void) broadcastThargoidDestroyed

Definition at line 9589 of file ShipEntity.m.

14053{
14054 [[UNIVERSE findShipsMatchingPredicate:HasRolePredicate
14055 parameter:@"tharglet"
14056 inRange:SCANNER_MAX_RANGE
14057 ofEntity:self]
14058 makeObjectsPerformSelector:@selector(sendAIMessage:) withObject:@"THARGOID_DESTROYED"];
14059}

◆ calculateTargetPosition

- (HPVector) calculateTargetPosition

Definition at line 2092 of file ShipEntity.m.

6297{
6298 Entity *target = [self primaryTarget];
6299 if (target == nil)
6300 {
6301 return kZeroHPVector;
6302 }
6303 if (reactionTime <= 0.0)
6304 {
6305 return [target position];
6306 }
6307 double t = [UNIVERSE getTime] - trackingCurveTimes[1];
6308 return HPvector_add(HPvector_add(trackingCurveCoeffs[0], HPvector_multiply_scalar(trackingCurveCoeffs[1],t)), HPvector_multiply_scalar(trackingCurveCoeffs[2],t*t));
6309}
const HPVector kZeroHPVector
Definition OOHPVector.m:28
OOTimeAbsolute trackingCurveTimes[4]
Definition ShipEntity.h:451
float reactionTime
Definition ShipEntity.h:449
HPVector trackingCurveCoeffs[3]
Definition ShipEntity.h:452

◆ calculateTrackingCurve

- (void) calculateTrackingCurve

Definition at line 2092 of file ShipEntity.m.

6361{
6362 if (reactionTime <= 0.0)
6363 {
6367 return;
6368 }
6369 double t1 = trackingCurveTimes[2] - trackingCurveTimes[1],
6372 trackingCurveCoeffs[1] = HPvector_add(HPvector_add(
6373 HPvector_multiply_scalar(trackingCurvePositions[1], -(t1+t2)/(t1*t2)),
6374 HPvector_multiply_scalar(trackingCurvePositions[2], -t2/(t1*(t1-t2)))),
6375 HPvector_multiply_scalar(trackingCurvePositions[3], t1/(t2*(t1-t2))));
6376 trackingCurveCoeffs[2] = HPvector_add(HPvector_add(
6377 HPvector_multiply_scalar(trackingCurvePositions[1], 1/(t1*t2)),
6378 HPvector_multiply_scalar(trackingCurvePositions[2], 1/(t1*(t1-t2)))),
6379 HPvector_multiply_scalar(trackingCurvePositions[3], -1/(t2*(t1-t2))));
6380 return;
6381}
HPVector trackingCurvePositions[4]
Definition ShipEntity.h:450

◆ canAcceptEscort:

- (BOOL) canAcceptEscort: (ShipEntity *)  potentialEscort

Definition at line 9589 of file ShipEntity.m.

13679 :(ShipEntity *)potentialEscort
13680{
13681 if (dockingInstructions) // we are busy with docking.
13682 {
13683 return NO;
13684 }
13685 if (scanClass != [potentialEscort scanClass]) // this makes sure that wingman can only select police, thargons only thargoids.
13686 {
13687 return NO;
13688 }
13689 if ([self bounty] == 0 && [potentialEscort bounty] != 0) // clean mothers can only accept clean escorts
13690 {
13691 return NO;
13692 }
13693 if (![self isEscort]) // self is NOT wingman or escort or thargon
13694 {
13695 return [potentialEscort isEscort]; // is wingman or escort or thargon
13696 }
13697 return NO;
13698}
BOOL isEscort()

◆ canAddEquipment:inContext:

- (BOOL) canAddEquipment: (NSString *)  equipmentKey
inContext: (NSString *)  context 

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3224 :(NSString *)equipmentKey inContext:(NSString *)context
3225{
3226 if ([equipmentKey hasSuffix:@"_DAMAGED"])
3227 {
3228 equipmentKey = [equipmentKey substringToIndex:[equipmentKey length] - [@"_DAMAGED" length]];
3229 }
3230
3231 NSString * lcEquipmentKey = [equipmentKey lowercaseString];
3232 if ([equipmentKey hasSuffix:@"MISSILE"]||[equipmentKey hasSuffix:@"MINE"]||([self isThargoid] && ([lcEquipmentKey hasPrefix:@"thargon"] || [lcEquipmentKey hasSuffix:@"thargon"])))
3233 {
3234 if (missiles >= max_missiles) return NO;
3235 }
3236
3238
3239 if (![eqType canCarryMultiple] && [self hasEquipmentItem:equipmentKey]) return NO;
3240 if (![self equipmentValidToAdd:equipmentKey inContext:context]) return NO;
3241
3242 return YES;
3243}

Referenced by ShipCanAwardEquipment().

+ Here is the caller graph for this function:

◆ canCollide

- (BOOL) canCollide
implementation

Reimplemented from Entity.

Reimplemented in PlayerEntity.

Definition at line 14942 of file ShipEntity.m.

2071{
2072 int status = [self status];
2073 if (status == STATUS_COCKPIT_DISPLAY || status == STATUS_DEAD || status == STATUS_BEING_SCOOPED)
2074 {
2075 return NO;
2076 }
2077
2078 if (isWreckage)
2079 {
2080 // wreckage won't collide
2081 return NO;
2082 }
2083
2084 if (isMissile && [self shotTime] < 0.25) // not yet fused
2085 {
2086 return NO;
2087 }
2088
2089 return YES;
2090}
unsigned isMissile
Definition ShipEntity.h:273
OOTimeDelta shotTime()

◆ canScoop:

- (BOOL) canScoop: (ShipEntity *)  other

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12854 :(ShipEntity*)other
12855{
12856 if (other == nil) return NO;
12857 if (![self hasCargoScoop]) return NO;
12858 if ([cargo count] >= [self maxAvailableCargoSpace]) return NO;
12859 if (scanClass == CLASS_CARGO) return NO; // we have no power so we can't scoop
12860 if ([other scanClass] != CLASS_CARGO) return NO;
12861 if ([other cargoType] == CARGO_NOT_CARGO) return NO;
12862
12863 if ([other isStation]) return NO;
12864
12865 HPVector loc = HPvector_between(position, [other position]);
12866
12867 if (dot_product(v_forward, HPVectorToVector(loc)) < 0.0f) return NO; // Must be in front of us
12868 if ([self isPlayer] && dot_product(v_up, HPVectorToVector(loc)) > 0.0f) return NO; // player has to scoop on underside, give more flexibility to NPCs
12869
12870 return YES;
12871}
Vector v_up
Definition ShipEntity.h:200
BOOL hasCargoScoop()

◆ canStillTrackPrimaryTarget

- (BOOL) canStillTrackPrimaryTarget

Definition at line 9589 of file ShipEntity.m.

10090{
10092 if (target == nil)
10093 {
10094 return NO;
10095 }
10096 if (![self isValidTarget:target])
10097 {
10098 return NO;
10099 }
10100 double range2 = HPmagnitude2(HPvector_subtract([target position], position));
10101 if (range2 > scannerRange * scannerRange * 1.5625)
10102 {
10103 // 1.5625 = 1.25*1.25
10104 return NO;
10105 }
10106 // 1.81: can retain cloaked ships as a *primary* target now
10107/* if ([target isShip] && [(ShipEntity*)target isCloaked])
10108 {
10109 return NO;
10110 } */
10111 return YES;
10112}
id primaryTargetWithoutValidityCheck()

◆ cargo

- (NSMutableArray *) cargo

◆ cargoFlag

- (OOCargoFlag) cargoFlag

Definition at line 7616 of file ShipEntity.m.

8509{
8510 return cargo_flag;
8511}
OOCargoFlag cargo_flag
Definition ShipEntity.h:299

◆ cargoListForScripting

- (NSArray *) cargoListForScripting

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8409{
8410 NSMutableArray *list = [NSMutableArray array];
8411
8412 OOCommodityType good = nil;
8413 NSArray *goods = [[UNIVERSE commodityMarket] goods];
8414 NSUInteger i, j, commodityCount = [goods count];
8415 OOCargoQuantity quantityInHold[commodityCount];
8416
8417 for (i = 0; i < commodityCount; i++)
8418 {
8419 quantityInHold[i] = 0;
8420 }
8421 for (i = 0; i < [cargo count]; i++)
8422 {
8423 ShipEntity *container = [cargo objectAtIndex:i];
8424 j = [goods indexOfObject:[container commodityType]];
8425 quantityInHold[j] += [container commodityAmount];
8426 }
8427
8428 for (i = 0; i < commodityCount; i++)
8429 {
8430 if (quantityInHold[i] > 0)
8431 {
8432 NSMutableDictionary *commodity = [NSMutableDictionary dictionaryWithCapacity:4];
8433 good = [goods objectAtIndex:i];
8434 // commodity, quantity - keep consistency between .manifest and .contracts
8435 [commodity setObject:good forKey:@"commodity"];
8436 [commodity setObject:[NSNumber numberWithUnsignedInt:quantityInHold[i]] forKey:@"quantity"];
8437 [commodity setObject:[[UNIVERSE commodityMarket] nameForGood:good] forKey:@"displayName"];
8438 [commodity setObject:DisplayStringForMassUnitForCommodity(good) forKey:@"unit"];
8439 [list addObject:commodity];
8440 }
8441 }
8442
8443 return [[list copy] autorelease]; // return an immutable copy
8444}
NSString * OOCommodityType
Definition OOTypes.h:106
uint32_t OOCargoQuantity
Definition OOTypes.h:176
OOCargoQuantity commodityAmount()
OOCommodityType commodityType()

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ cargoQuantityOnBoard

- (OOCargoQuantity) cargoQuantityOnBoard

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8386{
8387 NSUInteger result = [[self cargo] count];
8388 NSAssert(result < UINT32_MAX, @"Cargo quantity out of bounds.");
8389 return (OOCargoQuantity)result;
8390}

◆ cargoType

- (OOCargoType) cargoType

Definition at line 7616 of file ShipEntity.m.

8395{
8396 return cargo_type;
8397}
OOCargoType cargo_type
Definition ShipEntity.h:298

◆ cascadeIfAppropriateWithDamageAmount:cascadeOwner:

- (BOOL) cascadeIfAppropriateWithDamageAmount: (double)  amount
cascadeOwner: (Entity *)  owner 

Definition at line 9589 of file ShipEntity.m.

13078 :(double)amount cascadeOwner:(Entity *)owner
13079{
13080 BOOL cascade = NO;
13081 switch ([self scanClass])
13082 {
13083 case CLASS_WORMHOLE:
13084 case CLASS_ROCK:
13085 case CLASS_CARGO:
13086 case CLASS_VISUAL_EFFECT:
13087 case CLASS_BUOY:
13088 // does not normally cascade
13089 if ((fuel > MIN_FUEL) || isStation)
13090 {
13091 //we have fuel onboard so we can still go pop, or we are a station which can
13092 }
13093 else break;
13094
13095 case CLASS_STATION:
13096 case CLASS_MINE:
13097 case CLASS_PLAYER:
13098 case CLASS_POLICE:
13099 case CLASS_MILITARY:
13100 case CLASS_THARGOID:
13101 case CLASS_MISSILE:
13102 case CLASS_NOT_SET:
13103 case CLASS_NO_DRAW:
13104 case CLASS_NEUTRAL:
13105 case CLASS_TARGET:
13106 // ...start a chain reaction, if we're dying and have a non-trivial amount of energy.
13107 if (energy < amount && energy > 10 && [self countsAsKill])
13108 {
13109 cascade = YES; // confirm we're cascading, then try to add our cascade to UNIVERSE.
13110 [UNIVERSE addEntity:[OOQuiriumCascadeEntity quiriumCascadeFromShip:self]];
13111 }
13112 break;
13113 //no default thanks, we want the compiler to tell us if we missed a case.
13114 }
13115 return cascade;
13116}
BOOL countsAsKill()

◆ checkAegis

- (void) checkAegis
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1461{
1462 switch (aegis_status)
1463 {
1465 [shipAI message:@"AEGIS_CLOSE_TO_MAIN_PLANET"];
1466 // It's been a few years since 1.71 - it should be safe enough to comment out the line below for 1.77/1.78 -- Kaks 20120917
1467 //[shipAI message:@"AEGIS_CLOSE_TO_PLANET"]; // fires only for main planets, kept for compatibility with pre-1.72 AI plists.
1468 return;
1470 {
1471 Entity<OOStellarBody> *nearest = [self findNearestStellarBody];
1472
1473 if([nearest isSun])
1474 {
1475 [shipAI message:@"CLOSE_TO_SUN"];
1476 }
1477 else
1478 {
1479 [shipAI message:@"CLOSE_TO_PLANET"];
1480 if ([nearest planetType] == STELLAR_TYPE_MOON)
1481 {
1482 [shipAI message:@"CLOSE_TO_MOON"];
1483 }
1484 else
1485 {
1486 [shipAI message:@"CLOSE_TO_SECONDARY_PLANET"];
1487 }
1488 }
1489 return;
1490 }
1492 [shipAI message:@"AEGIS_IN_DOCKING_RANGE"];
1493 return;
1494 case AEGIS_NONE:
1495 [shipAI message:@"AEGIS_NONE"];
1496 return;
1497 }
1498
1499 NSLog(@"Aegis status for %@ has taken on invalid value %i. This is an internal error, please report it.", self, aegis_status);
1500 aegis_status = AEGIS_NONE;
1501 [shipAI message:@"AEGIS_NONE"];
1502}
#define NSLog(format,...)
Definition OOLogging.h:137
@ STELLAR_TYPE_MOON
@ AEGIS_IN_DOCKING_RANGE
Definition OOTypes.h:64
@ AEGIS_CLOSE_TO_MAIN_PLANET
Definition OOTypes.h:63
@ AEGIS_CLOSE_TO_ANY_PLANET
Definition OOTypes.h:62
@ AEGIS_NONE
Definition OOTypes.h:61

◆ checkCloseCollisionWith:

- (BOOL) checkCloseCollisionWith: (Entity *)  other
implementation

Reimplemented from Entity.

Definition at line 2092 of file ShipEntity.m.

2168 :(Entity *)other
2169{
2170 if (other == nil) return NO;
2171 if ([collidingEntities containsObject:other]) return NO; // we know about this already!
2172
2173 ShipEntity *otherShip = nil;
2174 if ([other isShip]) otherShip = (ShipEntity *)other;
2175
2176 if ([self canScoop:otherShip]) return YES; // quick test - could this improve scooping for small ships? I think so!
2177
2178 if (otherShip != nil && trackCloseContacts)
2179 {
2180 // in update we check if close contacts have gone out of touch range (origin within our collision_radius)
2181 // here we check if something has come within that range
2182 HPVector otherPos = [otherShip position];
2183 OOUniversalID otherID = [otherShip universalID];
2184 NSString *other_key = [NSString stringWithFormat:@"%d", otherID];
2185
2186 if (![closeContactsInfo objectForKey:other_key] &&
2187 HPdistance2(position, otherPos) < collision_radius * collision_radius)
2188 {
2189 // calculate position with respect to our own position and orientation
2190 Vector dpos = HPVectorToVector(HPvector_between(position, otherPos));
2191 Vector rpos = make_vector(dot_product(dpos, v_right), dot_product(dpos, v_up), dot_product(dpos, v_forward));
2192 [closeContactsInfo setObject:[NSString stringWithFormat:@"%f %f %f", rpos.x, rpos.y, rpos.z] forKey: other_key];
2193
2194 // send AI a message about the touch
2196 _primaryTarget = [otherShip weakRetain];
2197 [self doScriptEvent:OOJSID("shipCloseContact") withArgument:otherShip andReactToAIMessage:@"CLOSE CONTACT"];
2198 _primaryTarget = temp;
2199 }
2200 }
2201
2202 /* This does not appear to save a significant amount of time in
2203 * most situations. No significant change in frame rate with a
2204 * 350-segment planetary ring at 1400 collision candidates, even
2205 * on old hardware. There are perhaps situations in which it could
2206 * be a significant optimisation, but those are likely to also be
2207 * the situations where the effect of adding hundreds of extra
2208 * false-positive collisions leaves the player returning to a
2209 * mess... So, commented out: CIM 21 Jan 2014
2210 if (zero_distance > CLOSE_COLLISION_CHECK_MAX_RANGE2) // don't work too hard on entities that are far from the player
2211 return YES;
2212 */
2213
2214 if (otherShip != nil)
2215 {
2216 // check hull octree versus other hull octree
2217 collider = doOctreesCollide(self, otherShip);
2218 return (collider != nil);
2219 }
2220
2221 // default at this stage is to say YES they've collided!
2222 collider = other;
2223 return YES;
2224}
uint16_t OOUniversalID
Definition OOTypes.h:189
NSMutableArray * collidingEntities
Definition Entity.h:148
Entity * collider
Definition Entity.h:128
unsigned trackCloseContacts
Definition ShipEntity.h:262
ShipEntity * doOctreesCollide(ShipEntity *prime, ShipEntity *other)
NSMutableDictionary * closeContactsInfo
Definition ShipEntity.h:402
Vector v_right
Definition ShipEntity.h:200

◆ checkCourseToDestination

- (void) checkCourseToDestination
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1442{
1443 Entity *hazard = [UNIVERSE hazardOnRouteFromEntity: self toDistance: desired_range fromPoint: _destination];
1444
1445 if (hazard == nil || ([hazard isShip] && HPdistance(position, [hazard position]) > scannerRange) || ([hazard isPlanet] && aegis_status == AEGIS_NONE))
1446 [shipAI message:@"COURSE_OK"]; // Avoid going into a waypoint.plist for far away objects, it cripples the main AI a bit in its funtionality.
1447 else
1448 {
1449 if ([hazard isShip] && (weapon_damage * 24.0 > [hazard energy]))
1450 {
1451 [shipAI reactToMessage:@"HAZARD_CAN_BE_DESTROYED" context:@"checkCourseToDestination"];
1452 }
1453
1454 _destination = [UNIVERSE getSafeVectorFromEntity:self toDistance:desired_range fromPoint:_destination];
1455 [shipAI message:@"WAYPOINT_SET"];
1456 }
1457}

◆ checkDistanceTravelled

- (void) checkDistanceTravelled
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1771{
1772 if (distanceTravelled > desired_range)
1773 [shipAI message:@"GONE_BEYOND_RANGE"];
1774}

◆ checkEnergy

- (void) checkEnergy
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1506{
1507 if (energy == maxEnergy)
1508 {
1509 [shipAI message:@"ENERGY_FULL"];
1510 return;
1511 }
1512 if (energy >= maxEnergy * 0.75)
1513 {
1514 [shipAI message:@"ENERGY_HIGH"];
1515 return;
1516 }
1517 if (energy <= maxEnergy * 0.25)
1518 {
1519 [shipAI message:@"ENERGY_LOW"];
1520 return;
1521 }
1522 [shipAI message:@"ENERGY_MEDIUM"];
1523}

◆ checkForAegis

- (OOAegisStatus) checkForAegis

Definition at line 7616 of file ShipEntity.m.

7709{
7710 Entity<OOStellarBody> *nearest = [self findNearestStellarBody];
7711 BOOL sunGoneNova = [[UNIVERSE sun] goneNova];
7712
7713 if (nearest == nil)
7714 {
7715 if (aegis_status != AEGIS_NONE)
7716 {
7717 // Planet disappeared!
7718 [self transitionToAegisNone];
7719 }
7720 return AEGIS_NONE;
7721 }
7722 // check planet
7723 float cr = [nearest radius];
7724 float cr2 = cr * cr;
7725 OOAegisStatus result = AEGIS_NONE;
7726 float d2 = HPmagnitude2(HPvector_subtract([nearest position], [self position]));
7727 // not scannerRange: aegis shouldn't depend on that
7728 float sd2 = SCANNER_MAX_RANGE2 * 10.0f;
7729
7730 // check if nearing a surface
7731 unsigned wasNearPlanetSurface = isNearPlanetSurface; // isNearPlanetSurface is a bit flag, not an actual BOOL
7732 isNearPlanetSurface = (d2 - cr2) < (250000.0f + 1000.0f * cr); //less than 500m from the surface: (a+b)*(a+b) = a*a+b*b +2*a*b
7733
7734
7735 if (EXPECT_NOT((wasNearPlanetSurface != isNearPlanetSurface) && !suppressAegisMessages))
7736 {
7738 {
7739 [self doScriptEvent:OOJSID("shipApproachingPlanetSurface") withArgument:nearest];
7740 [shipAI reactToMessage:@"APPROACHING_SURFACE" context:@"flight update"];
7741 }
7742 else
7743 {
7744 [self doScriptEvent:OOJSID("shipLeavingPlanetSurface") withArgument:nearest];
7745 [shipAI reactToMessage:@"LEAVING_SURFACE" context:@"flight update"];
7746 }
7747 }
7748
7749 // being close to the station takes precedence over planets
7750 StationEntity *the_station = [UNIVERSE station];
7751 if (the_station)
7752 {
7753 sd2 = HPmagnitude2(HPvector_subtract([the_station position], [self position]));
7754 }
7755 // again, notional scanner range is intentional
7756 if (sd2 < SCANNER_MAX_RANGE2 * 4.0f) // double scanner range
7757 {
7758 result = AEGIS_IN_DOCKING_RANGE;
7759 }
7760 else if (EXPECT_NOT(isNearPlanetSurface || d2 < cr2 * 9.0f)) // to 3x radius of any planet/moon - or 500m of tiny ones,
7761 {
7763 if (EXPECT((OOPlanetEntity *)nearest == [UNIVERSE planet]))
7764 {
7766 }
7767 }
7768 // need to do this check separately from above case to avoid oddity where
7769 // main planet and small moon are at just the wrong distance. - CIM
7770 if (result != AEGIS_CLOSE_TO_MAIN_PLANET && result != AEGIS_IN_DOCKING_RANGE && !sunGoneNova)
7771 {
7772 // are we also close to the main planet?
7773 OOPlanetEntity *mainPlanet = [UNIVERSE planet];
7774 d2 = HPmagnitude2(HPvector_subtract([mainPlanet position], [self position]));
7775 cr2 = [mainPlanet radius];
7776 cr2 *= cr2;
7777 if (d2 < cr2 * 9.0f)
7778 {
7779 nearest = mainPlanet;
7781 }
7782 }
7783
7784
7785 /* Rewrote aegis stuff and tested it against redux.oxp that adds multiple planets and moons.
7786 Made sure AI scripts can differentiate between MAIN and NON-MAIN planets so they can decide
7787 if they can dock at the systemStation or just any station.
7788 Added sun detection so route2Patrol can turn before they heat up in the sun.
7789 -- Eric 2009-07-11
7790
7791 More rewriting of the aegis stuff, it's now a bit faster and works properly when moving
7792 from one secondary planet/moon vicinity to another one. -- Kaks 20120917
7793 */
7795 {
7796 // script/AI messages on change in status
7798 {
7799 [self doScriptEvent:OOJSID("shipExitedStationAegis") withArgument:the_station];
7800 [shipAI message:@"AEGIS_LEAVING_DOCKING_RANGE"];
7801 }
7802
7803 if (EXPECT_NOT(result == AEGIS_IN_DOCKING_RANGE && aegis_status != result))
7804 {
7805 [self doScriptEvent:OOJSID("shipEnteredStationAegis") withArgument:the_station];
7806 [shipAI message:@"AEGIS_IN_DOCKING_RANGE"];
7807
7808 if([self lastAegisLock] == nil && !sunGoneNova) // With small main planets the station aegis can come before planet aegis
7809 {
7810 [self doScriptEvent:OOJSID("shipEnteredPlanetaryVicinity") withArgument:[UNIVERSE planet]];
7811 [self setLastAegisLock:[UNIVERSE planet]];
7812 }
7813 }
7814 else if (EXPECT_NOT(result == AEGIS_NONE && aegis_status != result))
7815 {
7816 if([self lastAegisLock] == nil && !sunGoneNova)
7817 {
7818 [self setLastAegisLock:[UNIVERSE planet]]; // in case of a first launch from a near-planet station.
7819 }
7820 [self transitionToAegisNone];
7821 }
7822 // approaching..
7823 else if (EXPECT_NOT((result == AEGIS_CLOSE_TO_ANY_PLANET || result == AEGIS_CLOSE_TO_MAIN_PLANET) && [self lastAegisLock] != nearest))
7824 {
7825 if(aegis_status != AEGIS_NONE && [self lastAegisLock] != nil) // we were close to another stellar body
7826 {
7827 [self doScriptEvent:OOJSID("shipExitedPlanetaryVicinity") withArgument:[self lastAegisLock]];
7828 [shipAI message:@"AWAY_FROM_PLANET"]; // fires for suns, planets and moons.
7829 }
7830 [self doScriptEvent:OOJSID("shipEnteredPlanetaryVicinity") withArgument:nearest];
7831 [self setLastAegisLock:nearest];
7832
7833 if (EXPECT_NOT([nearest isSun]))
7834 {
7835 [shipAI message:@"CLOSE_TO_SUN"];
7836 }
7837 else
7838 {
7839 [shipAI message:@"CLOSE_TO_PLANET"];
7840
7841 if (EXPECT(result == AEGIS_CLOSE_TO_MAIN_PLANET))
7842 {
7843 // It's been years since 1.71 - it should be safe enough to comment out the line below for 1.77/1.78 -- Kaks 20120917
7844 //[shipAI message:@"AEGIS_CLOSE_TO_PLANET"]; // fires only for main planets, kept for compatibility with pre-1.72 AI plists.
7845 [shipAI message:@"AEGIS_CLOSE_TO_MAIN_PLANET"]; // fires only for main planet.
7846 }
7847 else if (EXPECT_NOT([nearest planetType] == STELLAR_TYPE_MOON))
7848 {
7849 [shipAI message:@"CLOSE_TO_MOON"];
7850 }
7851 else
7852 {
7853 [shipAI message:@"CLOSE_TO_SECONDARY_PLANET"];
7854 }
7855 }
7856 }
7857
7858
7859 }
7860 if (result == AEGIS_NONE)
7861 {
7862 [self setLastAegisLock:nil];
7863 }
7864
7865 aegis_status = result; // put this here
7866 return result;
7867}
OOAegisStatus
Definition OOTypes.h:60
BOOL isSun()
Definition Entity.m:168
unsigned isNearPlanetSurface
Definition ShipEntity.h:263
unsigned suppressAegisMessages
Definition ShipEntity.h:272
OOAegisStatus aegis_status
Definition ShipEntity.h:378
Entity< OOStellarBody > * lastAegisLock()

◆ checkForFullHold

- (void) checkForFullHold
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1164{
1165 if (!max_cargo)
1166 {
1167 [shipAI message:@"NO_CARGO_BAY"];
1168 }
1169 else if ([cargo count] >= [self maxAvailableCargoSpace])
1170 {
1171 [shipAI message:@"HOLD_FULL"];
1172 }
1173 else
1174 {
1175 [shipAI message:@"HOLD_NOT_FULL"];
1176 }
1177}

◆ checkForMotherStation

- (void) checkForMotherStation
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2060{
2061 ShipEntity *motherStation = [[self group] leader];
2062 if ((!motherStation) || (!(motherStation->isStation)))
2063 {
2064 [shipAI message:@"NOTHING_FOUND"];
2065 return;
2066 }
2067 double found_d2 = scannerRange * scannerRange;
2068 HPVector v0 = motherStation->position;
2069 if (HPdistance2(v0,position) > found_d2)
2070 {
2071 [shipAI message:@"NOTHING_FOUND"];
2072 return;
2073 }
2074 [shipAI message:@"STATION_FOUND"];
2075}

◆ checkForNormalSpace

- (void) checkForNormalSpace
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2475{
2476 if ([UNIVERSE sun] && [UNIVERSE planet])
2477 [shipAI message:@"NORMAL_SPACE"];
2478 else
2479 [shipAI message:@"INTERSTELLAR_SPACE"];
2480}

◆ checkFoundTarget

- (void) checkFoundTarget
implementation

Provided by category ShipEntity(OOAIPrivate).

Definition at line 1 of file ShipEntityAI.m.

2739{
2740 if ([self foundTarget] != nil)
2741 {
2742 [shipAI message:@"TARGET_FOUND"];
2743 }
2744 else
2745 {
2746 [shipAI message:@"NOTHING_FOUND"];
2747 }
2748}

◆ checkGroupOddsVersusTarget

- (void) checkGroupOddsVersusTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1853{
1854 NSUInteger ownGroupCount = [[self group] count] + (ranrot_rand() & 3); // add a random fudge factor
1855 NSUInteger targetGroupCount = [[[self primaryTarget] group] count] + (ranrot_rand() & 3); // add a random fudge factor
1856
1857 if (ownGroupCount == targetGroupCount)
1858 {
1859 [shipAI message:@"ODDS_LEVEL"];
1860 }
1861 else if (ownGroupCount > targetGroupCount)
1862 {
1863 [shipAI message:@"ODDS_GOOD"];
1864 }
1865 else
1866 {
1867 [shipAI message:@"ODDS_BAD"];
1868 }
1869}

◆ checkHeatInsulation

- (void) checkHeatInsulation
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1526{
1527 float minInsulation = 1000 / [self maxFlightSpeed] + 1;
1528
1529 if ([self heatInsulation] < minInsulation)
1530 {
1531 [shipAI message:@"INSULATION_POOR"];
1532 return;
1533 }
1534 [shipAI message:@"INSULATION_OK"];
1535}

◆ checkOwnLegalStatus

- (void) checkOwnLegalStatus
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1386{
1387 if (scanClass == CLASS_THARGOID)
1388 {
1389 [shipAI message:@"SELF_THARGOID"];
1390 return;
1391 }
1392 int ls = [self legalStatus];
1393 if (ls > 50)
1394 {
1395 [shipAI message:@"SELF_FUGITIVE"];
1396 return;
1397 }
1398 if (ls > 20)
1399 {
1400 [shipAI message:@"SELF_OFFENDER"];
1401 return;
1402 }
1403 if (ls > 0)
1404 {
1405 [shipAI message:@"SELF_MINOR_OFFENDER"];
1406 return;
1407 }
1408 [shipAI message:@"SELF_CLEAN"];
1409}

◆ checkScanner

- (void) checkScanner

Definition at line 9589 of file ShipEntity.m.

9814{
9815 Entity* scan;
9816 n_scanned_ships = 0;
9817 //
9818 scan = z_previous; while ((scan)&&(scan->isShip == NO)) scan = scan->z_previous; // skip non-ships
9819 GLfloat scannerRange2 = scannerRange * scannerRange;
9820 while ((scan)&&(scan->position.z > position.z - scannerRange)&&(n_scanned_ships < MAX_SCAN_NUMBER))
9821 {
9822 // can't scan cloaked ships
9823 if (scan->isShip && ![(ShipEntity*)scan isCloaked] && [self isValidTarget:scan])
9824 {
9825 distance2_scanned_ships[n_scanned_ships] = HPdistance2(position, scan->position);
9826 if (distance2_scanned_ships[n_scanned_ships] < scannerRange2)
9827 scanned_ships[n_scanned_ships++] = (ShipEntity*)scan;
9828 }
9829 scan = scan->z_previous; while ((scan)&&(scan->isShip == NO)) scan = scan->z_previous;
9830 }
9831 //
9832 scan = z_next; while ((scan)&&(scan->isShip == NO)) scan = scan->z_next; // skip non-ships
9833 while ((scan)&&(scan->position.z < position.z + scannerRange)&&(n_scanned_ships < MAX_SCAN_NUMBER))
9834 {
9835 if (scan->isShip && ![(ShipEntity*)scan isCloaked] && [self isValidTarget:scan])
9836 {
9837 distance2_scanned_ships[n_scanned_ships] = HPdistance2(position, scan->position);
9838 if (distance2_scanned_ships[n_scanned_ships] < scannerRange2)
9839 scanned_ships[n_scanned_ships++] = (ShipEntity*)scan;
9840 }
9841 scan = scan->z_next; while ((scan)&&(scan->isShip == NO)) scan = scan->z_next; // skip non-ships
9842 }
9843 //
9844 scanned_ships[n_scanned_ships] = nil; // terminate array
9845}
#define MAX_SCAN_NUMBER
Definition ShipEntity.h:97
Entity * z_next
Definition Entity.h:122
Entity * z_previous
Definition Entity.h:122
GLfloat distance2_scanned_ships[MAX_SCAN_NUMBER+1]
Definition ShipEntity.h:414

◆ checkScannerIgnoringUnpowered

- (void) checkScannerIgnoringUnpowered

Definition at line 9589 of file ShipEntity.m.

9849{
9850 Entity* scan;
9851 n_scanned_ships = 0;
9852 //
9853 GLfloat scannerRange2 = scannerRange * scannerRange;
9854 scan = z_previous;
9855 while ((scan)&&((scan->isShip == NO)||(scan->scanClass==CLASS_ROCK)||(scan->scanClass==CLASS_CARGO)))
9856 {
9857 scan = scan->z_previous; // skip non-ships
9858 }
9859 while ((scan)&&(scan->position.z > position.z - scannerRange)&&(n_scanned_ships < MAX_SCAN_NUMBER))
9860 {
9861 if (scan->isShip && ![(ShipEntity*)scan isCloaked])
9862 {
9863 distance2_scanned_ships[n_scanned_ships] = HPdistance2(position, scan->position);
9864 if (distance2_scanned_ships[n_scanned_ships] < scannerRange2)
9865 scanned_ships[n_scanned_ships++] = (ShipEntity*)scan;
9866 }
9867 scan = scan->z_previous;
9868 while ((scan)&&((scan->isShip == NO)||(scan->scanClass==CLASS_ROCK)||(scan->scanClass==CLASS_CARGO)))
9869 {
9870 scan = scan->z_previous; // skip non-ships
9871 }
9872 }
9873 //
9874 scan = z_next;
9875 while ((scan)&&((scan->isShip == NO)||(scan->scanClass==CLASS_ROCK)||(scan->scanClass==CLASS_CARGO)))
9876 {
9877 scan = scan->z_next; // skip non-ships
9878 }
9879
9880 while ((scan)&&(scan->position.z < position.z + scannerRange)&&(n_scanned_ships < MAX_SCAN_NUMBER))
9881 {
9882 if (scan->isShip && ![(ShipEntity*)scan isCloaked])
9883 {
9884 distance2_scanned_ships[n_scanned_ships] = HPdistance2(position, scan->position);
9885 if (distance2_scanned_ships[n_scanned_ships] < scannerRange2)
9886 scanned_ships[n_scanned_ships++] = (ShipEntity*)scan;
9887 }
9888 scan = scan->z_next;
9889 while ((scan)&&((scan->isShip == NO)||(scan->scanClass==CLASS_ROCK)||(scan->scanClass==CLASS_CARGO)))
9890 {
9891 scan = scan->z_next; // skip non-ships
9892 }
9893 }
9894 //
9895 scanned_ships[n_scanned_ships] = nil; // terminate array
9896}
OOScanClass scanClass
Definition Entity.h:106

◆ checkShipsInVicinityForWitchJumpExit

- (int) checkShipsInVicinityForWitchJumpExit

Definition at line 14062 of file ShipEntity.m.

14331{
14332 // checks if there are any large masses close by
14333 // since we want to place the space station at least 10km away
14334 // the formula we'll use is K x m / d2 < 1.0
14335 // (m = mass, d2 = distance squared)
14336 // coriolis station is mass 455,223,200
14337 // 10km is 10,000m,
14338 // 10km squared is 100,000,000
14339 // therefore K is 0.22 (approx)
14340
14341 int result = NO_TARGET;
14342
14343 GLfloat k = 0.1;
14344
14345 int ent_count = UNIVERSE->n_entities;
14346 Entity** uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
14347 ShipEntity* my_entities[ent_count];
14348 int i;
14349
14350 int ship_count = 0;
14351 for (i = 0; i < ent_count; i++)
14352 if ((uni_entities[i]->isShip)&&(uni_entities[i] != self))
14353 my_entities[ship_count++] = (ShipEntity*)[uni_entities[i] retain]; // retained
14354 //
14355 for (i = 0; (i < ship_count)&&(result == NO_TARGET) ; i++)
14356 {
14357 ShipEntity* ship = my_entities[i];
14358 HPVector delta = HPvector_between(position, ship->position);
14359 GLfloat d2 = HPmagnitude2(delta);
14360 if (![ship isPlayer] || ![PLAYER isDocked])
14361 { // player doesn't block if docked
14362 if ((k * [ship mass] > d2)&&(d2 < SCANNER_MAX_RANGE2)) // if you go off (typical) scanner from a blocker - it ceases to block
14363 result = [ship universalID];
14364 }
14365 }
14366 for (i = 0; i < ship_count; i++)
14367 [my_entities[i] release]; // released
14368
14369 return result;
14370}

◆ checkTargetLegalStatus

- (void) checkTargetLegalStatus
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1355{
1356 ShipEntity *other_ship = [self primaryTarget];
1357 if (!other_ship)
1358 {
1359 [shipAI message:@"NO_TARGET"];
1360 return;
1361 }
1362 else
1363 {
1364 int ls = [other_ship legalStatus];
1365 if (ls > 50)
1366 {
1367 [shipAI message:@"TARGET_FUGITIVE"];
1368 return;
1369 }
1370 if (ls > 20)
1371 {
1372 [shipAI message:@"TARGET_OFFENDER"];
1373 return;
1374 }
1375 if (ls > 0)
1376 {
1377 [shipAI message:@"TARGET_MINOR_OFFENDER"];
1378 return;
1379 }
1380 [shipAI message:@"TARGET_CLEAN"];
1381 }
1382}
int legalStatus()

◆ clearSubEntities

- (void) clearSubEntities

Definition at line 14942 of file ShipEntity.m.

1156{
1157 [subEntities makeObjectsPerformSelector:@selector(setOwner:) withObject:nil]; // Ensure backlinks are broken
1158 [subEntities release];
1159 subEntities = nil;
1160
1161 // reset size & mass!
1162 collision_radius = [self findCollisionRadius];
1164 float density = [[self shipInfoDictionary] oo_floatForKey:@"density" defaultValue:1.0f];
1165 if (octree) mass = (GLfloat)(density * 20.0f * [octree volume]);
1166}
float volume()
Octree * octree
Definition ShipEntity.h:423

Referenced by ShipRestoreSubEntities().

+ Here is the caller graph for this function:

◆ collectBountyFor:

- (void) collectBountyFor: (ShipEntity *)  other

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

9682 :(ShipEntity *)other
9683{
9684 if ([other isPolice]) // oops, we shot a copper!
9685 {
9686 [self markAsOffender:64 withReason:kOOLegalStatusReasonAttackedPolice];
9687 }
9688}
BOOL isPolice()

◆ collideWithShip:

- (BOOL) collideWithShip: (ShipEntity *)  other

Reimplemented in StationEntity.

Definition at line 9589 of file ShipEntity.m.

12669 :(ShipEntity *)other
12670{
12671 HPVector hploc;
12672 Vector loc;
12673 double dam1, dam2;
12674
12675 if (!other)
12676 return NO;
12677
12678 ShipEntity* otherParent = [other parentEntity];
12679 BOOL otherIsStation = other == [UNIVERSE station];
12680 // calculate line of centers using centres
12681 hploc = HPvector_normal_or_zbasis(HPvector_subtract([other absolutePositionForSubentity], position));
12682 loc = HPVectorToVector(hploc);
12683
12684
12685 if ([self canScoop:other])
12686 {
12687 [self scoopIn:other];
12688 return NO;
12689 }
12690 if ([other canScoop:self])
12691 {
12692 [other scoopIn:self];
12693 return NO;
12694 }
12695 if (universalID == NO_TARGET)
12696 return NO;
12697 if (other->universalID == NO_TARGET)
12698 return NO;
12699
12700 // find velocity along line of centers
12701 //
12702 // momentum = mass x velocity
12703 // ke = mass x velocity x velocity
12704 //
12705 GLfloat m1 = mass; // mass of self
12706 GLfloat m2 = [other mass]; // mass of other
12707
12708 // starting velocities:
12709 Vector v, vel1b = [self velocity];
12710
12711 if (otherParent != nil)
12712 {
12713 // Subentity
12714 /* TODO: if the subentity is rotating (subentityRotationalVelocity is
12715 not 1 0 0 0) we should calculate the tangential velocity from the
12716 other's position relative to our absolute position and add that in.
12717 */
12718 v = [otherParent velocity];
12719 }
12720 else
12721 {
12722 v = [other velocity];
12723 }
12724
12725 v = vector_subtract(vel1b, v);
12726
12727 GLfloat v2b = dot_product(v, loc); // velocity of other along loc before collision
12728
12729 GLfloat v1a = sqrt(v2b * v2b * m2 / m1); // velocity of self along loc after elastic collision
12730 if (v2b < 0.0f) v1a = -v1a; // in same direction as v2b
12731
12732 // are they moving apart at over 1m/s already?
12733 if (v2b < 0.0f)
12734 {
12735 if (v2b < -1.0f) return NO;
12736 else
12737 {
12738 position = HPvector_subtract(position, hploc); // adjust self position
12739 v = kZeroVector; // go for the 1m/s solution
12740 }
12741 }
12742
12743 // convert change in velocity into damage energy (KE)
12744 dam1 = m2 * v2b * v2b / 50000000;
12745 dam2 = m1 * v2b * v2b / 50000000;
12746
12747 // calculate adjustments to velocity after collision
12748 Vector vel1a = vector_multiply_scalar(loc, -v1a);
12749 Vector vel2a = vector_multiply_scalar(loc, v2b);
12750
12751 if (magnitude2(v) <= 0.1) // virtually no relative velocity - we must provide at least 1m/s to avoid conjoined objects
12752 {
12753 vel1a = vector_multiply_scalar(loc, -1);
12754 vel2a = loc;
12755 }
12756
12757 // apply change in velocity
12758 if (otherParent != nil)
12759 {
12760 [otherParent adjustVelocity:vel2a]; // move the otherParent not the subentity
12761 }
12762 else
12763 {
12764 [other adjustVelocity:vel2a];
12765 }
12766
12767 [self adjustVelocity:vel1a];
12768
12769 BOOL selfDestroyed = (dam1 > energy);
12770 BOOL otherDestroyed = (dam2 > [other energy]) && !otherIsStation;
12771
12772 if (dam1 > 0.05)
12773 {
12774 [self takeScrapeDamage: dam1 from:other];
12775 if (selfDestroyed) // inelastic! - take xplosion velocity damage instead
12776 {
12777 vel2a = vector_multiply_scalar(vel2a, -1);
12778 [other adjustVelocity:vel2a];
12779 }
12780 }
12781
12782 if (dam2 > 0.05)
12783 {
12784 if (otherParent != nil && ![otherParent isFrangible])
12785 {
12786 [otherParent takeScrapeDamage: dam2 from:self];
12787 }
12788 else
12789 {
12790 [other takeScrapeDamage: dam2 from:self];
12791 }
12792
12793 if (otherDestroyed) // inelastic! - take explosion velocity damage instead
12794 {
12795 vel1a = vector_multiply_scalar(vel1a, -1);
12796 [self adjustVelocity:vel1a];
12797 }
12798 }
12799
12800 if (!selfDestroyed && !otherDestroyed)
12801 {
12802 float t = 10.0 * [UNIVERSE getTimeDelta]; // 10 ticks
12803
12804 HPVector pos1a = HPvector_add([self position], vectorToHPVector(vector_multiply_scalar(loc, t * v1a)));
12805 [self setPosition:pos1a];
12806
12807 if (!otherIsStation)
12808 {
12809 HPVector pos2a = HPvector_add([other position], vectorToHPVector(vector_multiply_scalar(loc, t * v2b)));
12810 [other setPosition:pos2a];
12811 }
12812 }
12813
12814 // remove self from other's collision list
12815 [[other collisionArray] removeObject:self];
12816
12817 [self doScriptEvent:OOJSID("shipCollided") withArgument:other andReactToAIMessage:@"COLLISION"];
12818 [other doScriptEvent:OOJSID("shipCollided") withArgument:self andReactToAIMessage:@"COLLISION"];
12819
12820 return YES;
12821}
HPVector absolutePositionForSubentity()
Definition Entity.m:670
NSMutableArray * collisionArray()
Definition Entity.m:924
ShipEntity * parentEntity()
Definition Entity.m:590
void doScriptEvent:withArgument:andReactToAIMessage:(jsid scriptEvent,[withArgument] id argument,[andReactToAIMessage] NSString *aiMessage)
unsigned isFrangible
Definition ShipEntity.h:264
void takeScrapeDamage:from:(double amount,[from] Entity *ent)
void scoopIn:(ShipEntity *other)
void adjustVelocity:(Vector xVel)

◆ collisionExceptedFor:

- (BOOL) collisionExceptedFor: (ShipEntity *)  ship

Definition at line 9589 of file ShipEntity.m.

11142 :(ShipEntity *)ship
11143{
11145 {
11146 return NO;
11147 }
11148 return [_collisionExceptions containsObject:ship];
11149}

◆ collisionExceptions

- (NSArray *) collisionExceptions

Definition at line 9589 of file ShipEntity.m.

11113{
11115 {
11116 return [NSArray array];
11117 }
11118 return [_collisionExceptions allObjects];
11119}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ commodityAmount

- (OOCargoQuantity) commodityAmount

Definition at line 7616 of file ShipEntity.m.

8360{
8361 return commodity_amount;
8362}
OOCargoQuantity commodity_amount
Definition ShipEntity.h:364

◆ commodityType

- (OOCommodityType) commodityType

Definition at line 7616 of file ShipEntity.m.

8354{
8355 return commodity_type;
8356}
OOCommodityType commodity_type
Definition ShipEntity.h:363

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ commsMessage:

- (void) commsMessage: (NSString *)  valueString
implementation

Reimplemented in PlayerEntity.

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1658 :(NSString *)valueString
1659{
1660 [self commsMessage:valueString withUnpilotedOverride:NO];
1661}

◆ commsMessage:withUnpilotedOverride:

- (void) commsMessage: (NSString *)  valueString
withUnpilotedOverride: (BOOL)  unpilotedOverride 

Definition at line 14062 of file ShipEntity.m.

14234 :(NSString *)valueString withUnpilotedOverride:(BOOL)unpilotedOverride
14235{
14236 Random_Seed very_random_seed;
14237 very_random_seed.a = rand() & 255;
14238 very_random_seed.b = rand() & 255;
14239 very_random_seed.c = rand() & 255;
14240 very_random_seed.d = rand() & 255;
14241 very_random_seed.e = rand() & 255;
14242 very_random_seed.f = rand() & 255;
14243 seed_RNG_only_for_planet_description(very_random_seed);
14244
14245 [self broadcastMessage:valueString withUnpilotedOverride:unpilotedOverride];
14246}
void seed_RNG_only_for_planet_description(Random_Seed s_seed)

Referenced by ShipCommsMessage().

+ Here is the caller graph for this function:

◆ commsMessageByUnpiloted:

- (void) commsMessageByUnpiloted: (NSString *)  valueString
implementation

Reimplemented in PlayerEntity.

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1664 :(NSString *)valueString
1665{
1666 [self commsMessage:valueString withUnpilotedOverride:YES];
1667}

◆ compareBeaconCodeWith:

- (NSComparisonResult) compareBeaconCodeWith: (Entity<OOBeaconEntity> *)  other
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 9589 of file ShipEntity.m.

9691 :(Entity<OOBeaconEntity> *) other
9692{
9693 return [[self beaconCode] compare:[other beaconCode] options: NSCaseInsensitiveSearch];
9694}

◆ ComparePlanetsBySurfaceDistance

- (NSComparisonResult) ComparePlanetsBySurfaceDistance (id)  i1
(id)  i2
(void *)  context 
implementation

Definition at line 7616 of file ShipEntity.m.

7617{
7618 HPVector p = [(ShipEntity*) context position];
7619 OOPlanetEntity* e1 = i1;
7620 OOPlanetEntity* e2 = i2;
7621
7622 float p1 = SurfaceDistanceSqaredV(p, e1);
7623 float p2 = SurfaceDistanceSqaredV(p, e2);
7624
7625 if (p1 < p2) return NSOrderedAscending;
7626 if (p1 > p2) return NSOrderedDescending;
7627
7628 return NSOrderedSame;
7629}
static float SurfaceDistanceSqaredV(HPVector reference, Entity< OOStellarBody > *stellar)

◆ considerFiringMissile:

- (void) considerFiringMissile: (double)  delta_t

Definition at line 9589 of file ShipEntity.m.

12125 :(double)delta_t
12126{
12127 int missile_chance = 0;
12128 int rhs = 3.2 / delta_t;
12129 if (rhs) missile_chance = 1 + (ranrot_rand() % rhs);
12130
12131 double hurt_factor = 16 * pow(energy/maxEnergy, 4.0);
12132 if (missiles > missile_chance * hurt_factor)
12133 {
12134 [self fireMissile];
12135 }
12136}

◆ contractListForScripting

- (NSArray *) contractListForScripting

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3322{
3323 return [NSArray array];
3324}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ coordinates

- (HPVector) coordinates

◆ coordinatesForEscortPosition:

- (HPVector) coordinatesForEscortPosition: (unsigned)  idx
implementation

Provided by category ShipEntity(Private).

Definition at line 9589 of file ShipEntity.m.

13812 :(unsigned)idx
13813{
13814 /*
13815 This function causes problems with Thargoids: their missiles (aka Thargons) are automatically
13816 added to the escorts group, and when a mother ship dies all thargons will attach themselves
13817 as escorts to the surviving battleships. This can lead to huge escort groups.
13818 TODO: better handling of Thargoid groups:
13819 - put thargons (& all other thargon missiles) in their own non-escort group perhaps?
13820 */
13821
13822 // The _escortPositions array is always MAX_ESCORTS long.
13823 // Kludge: return the same last escort position if we have escorts above MAX_ESCORTS...
13824 idx = MIN(idx, (unsigned)(MAX_ESCORTS - 1));
13825
13826 return HPvector_add(self->position, vectorToHPVector(quaternion_rotate_vector([self normalOrientation], _escortPositions[idx])));
13827}
#define MIN(A, B)
Definition OOMaths.h:111
Vector _escortPositions[MAX_ESCORTS]
Definition ShipEntity.h:471

◆ countEquipmentItem:

- (NSUInteger) countEquipmentItem: (NSString *)  eqkey

Definition at line 2092 of file ShipEntity.m.

3091 :(NSString *)eqkey
3092{
3093 NSString *eq = nil;
3094 NSUInteger count = 0;
3095 foreach (eq, _equipment)
3096 {
3097 if ([eqkey isEqualToString:eq])
3098 {
3099 ++count;
3100 }
3101 }
3102 return count;
3103}

Referenced by ShipEquipmentStatus().

+ Here is the caller graph for this function:

◆ countsAsKill

- (BOOL) countsAsKill

Definition at line 14942 of file ShipEntity.m.

1686{
1687 return [[self shipInfoDictionary] oo_boolForKey:@"counts_as_kill" defaultValue:YES];
1688}

◆ crew

- (NSArray *) crew

◆ crewForScripting

- (NSArray *) crewForScripting

Definition at line 7616 of file ShipEntity.m.

7976{
7977 if (crew == nil)
7978 {
7979 return nil;
7980 }
7981 OOCharacter *crewMember = nil;
7982 NSMutableArray *result = [NSMutableArray arrayWithCapacity:4];
7983 foreach (crewMember, crew)
7984 {
7985 NSDictionary *crewDict = [crewMember infoForScripting];
7986 [result addObject:crewDict];
7987 }
7988 return result;
7989}
NSDictionary * infoForScripting()

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ cruiseSpeed

- (double) cruiseSpeed

◆ currentAimTolerance

- (GLfloat) currentAimTolerance

Definition at line 9589 of file ShipEntity.m.

11280{
11281 GLfloat basic_aim = aim_tolerance;
11282 GLfloat best_cos = 0.99999; // ~45m in 10km (track won't go better than 40)
11284 {
11285 // better general targeting
11286 best_cos = 0.999999; // ~14m in 10km (track won't go better than 10)
11287 // if missing, aim better!
11288 basic_aim /= 1.0 + ((GLfloat)[self missedShots] / 4.0);
11289 }
11291 {
11292 // deadly shots
11293 best_cos = 0.9999999; // ~4m in 10km (track won't go better than 4)
11294 // and start with extremely good aim circle
11295 basic_aim /= 5.0;
11296 }
11298 { // bad shots with aft lasers
11299 basic_aim *= 1.3;
11300 }
11302 { // everyone a bit worse with side lasers
11304 { // especially these
11305 basic_aim *= 1.3 + randf();
11306 }
11307 else
11308 {
11309 basic_aim *= 1.3;
11310 }
11311 }
11312 // only apply glare if ship is not shadowed
11313 if (isSunlit) {
11314 OOSunEntity *sun = [UNIVERSE sun];
11315 if (sun)
11316 {
11317 GLfloat sunGlareAngularSize = atan([sun radius]/HPdistance([self position], [sun position])) * SUN_GLARE_MULT_FACTOR + (SUN_GLARE_ADD_FACTOR);
11318 GLfloat glareLevel = [self lookingAtSunWithThresholdAngleCos:cos(sunGlareAngularSize)] * (1.0f - [self sunGlareFilter]);
11319 if (glareLevel > 0.1f)
11320 {
11321 // looking towards sun can seriously mess up aim (glareLevel 0..1)
11322 basic_aim *= (1.0 + glareLevel*3.0);
11323// OOLog(@"aim.debug",@"Sun glare affecting aim: %f for %@",glareLevel,self);
11324 if (glareLevel > 0.5f)
11325 {
11326 // strong glare makes precise targeting impossible
11327 best_cos = 0.99999;
11328 }
11329 }
11330 }
11331 }
11332
11333
11334 GLfloat max_cos = sqrt(1-(basic_aim * basic_aim / 100000000.0));
11335
11336 if (max_cos < best_cos)
11337 {
11338 return max_cos;
11339 }
11340 return best_cos;
11341}
@ WEAPON_FACING_PORT
Definition OOTypes.h:231
@ WEAPON_FACING_STARBOARD
Definition OOTypes.h:232
unsigned isSunlit
Definition Entity.h:99
OOWeaponFacing currentWeaponFacing
Definition ShipEntity.h:312
GLfloat sunGlareFilter
Definition ShipEntity.h:286

◆ currentWeaponFacing

- (OOWeaponFacing) currentWeaponFacing

◆ damage

- (int) damage

Definition at line 7616 of file ShipEntity.m.

8831{
8832 return (int)(100 - (100 * energy / maxEnergy));
8833}

◆ deactivateCloakingDevice

- (void) deactivateCloakingDevice

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12369{
12371 {
12373 [self doScriptEvent:OOJSID("shipCloakDeactivated")];
12374 }
12375}

◆ dealEnergyDamage:atRange:withBias:

- (void) dealEnergyDamage: (GLfloat)  baseDamage
atRange: (GLfloat)  range
withBias: (GLfloat)  velocityBias 

Definition at line 7616 of file ShipEntity.m.

8836 :(GLfloat) baseDamage atRange:(GLfloat) range withBias:(GLfloat) velocityBias
8837{
8838 // this is limited to the player's scanner range
8839 GLfloat maxRange = fmin(range * sqrt(baseDamage), SCANNER_MAX_RANGE);
8840
8841 OOLog(@"missile.damage.calc", @"Range: %f | Damage: %f | MaxRange: %f",range,baseDamage,maxRange);
8842
8843 NSArray *targets = [UNIVERSE entitiesWithinRange:maxRange ofEntity:self];
8844 if ([targets count] > 0)
8845 {
8846 unsigned i;
8847 for (i = 0; i < [targets count]; i++)
8848 {
8849 Entity *e2 = [targets objectAtIndex:i];
8850 Vector p2 = [self vectorTo:e2];
8851 double ecr = [e2 collisionRadius];
8852 double d = (magnitude(p2) - ecr) / range;
8853 // base damage within defined range, inverse-square falloff outside
8854 double localDamage = baseDamage;
8855 OOLog(@"missile.damage.calc", @"Base damage: %f",baseDamage);
8856 if (velocityBias > 0)
8857 {
8858 Vector v2 = vector_subtract([self velocity], [e2 velocity]);
8859 double vSign = dot_product(vector_normal([self velocity]), vector_normal(p2));
8860 // vSign should always be positive for the missile's actual target
8861 // but might be negative for other nearby ships which are
8862 // actually moving further away from the missile
8863// double vMag = vSign > 0.0 ? magnitude(v2) : -magnitude(v2);
8864 double vMag = vSign * magnitude(v2);
8865 if (vMag > 1000.0) {
8866 vMag = 1000.0;
8867// cap effective closing speed to 1.0LM or injector-collisions can still do
8868// ridiculous damage
8869 }
8870
8871 localDamage += vMag * velocityBias;
8872 OOLog(@"missile.damage.calc",@"Velocity magnitude + sign: %f , %f",magnitude(v2),vSign);
8873 OOLog(@"missile.damage.calc",@"Velocity magnitude factor: %f",vMag);
8874 OOLog(@"missile.damage.calc",@"Velocity corrected damage: %f",localDamage);
8875 }
8876 double damage = (d > 1) ? localDamage / (d * d) : localDamage;
8877 OOLog(@"missile.damage.calc",@"%f at range %f (d=%f)",damage,magnitude(p2)-ecr,d);
8878 if (damage > 0.0)
8879 {
8880 if ([self owner])
8881 {
8882 [e2 takeEnergyDamage:damage from:self becauseOf:[self owner] weaponIdentifier:[self primaryRole]];
8883 }
8884 else
8885 {
8886 [e2 takeEnergyDamage:damage from:self becauseOf:self weaponIdentifier:[self primaryRole]];
8887 }
8888 }
8889 }
8890 }
8891
8892 /* the actual damage can't go more than S_M_R, so cap the range
8893 * for exploding purposes so that the visual appearance isn't
8894 * larger than that */
8895 if (range > SCANNER_MAX_RANGE / 4.0)
8896 {
8897 range = SCANNER_MAX_RANGE / 4.0;
8898 }
8899 // and a visual sign of the explosion
8900 // "fireball" explosion effect
8901 NSDictionary *explosion = [UNIVERSE explosionSetting:@"oolite-default-ship-explosion"];
8902 [UNIVERSE addEntity:[OOExplosionCloudEntity explosionCloudFromEntity:self withSize:range*3.0 andSettings:explosion]];
8903
8904}
#define SCANNER_MAX_RANGE
Definition Entity.h:51
void takeEnergyDamage:from:becauseOf:weaponIdentifier:(double amount,[from] Entity *ent,[becauseOf] Entity *other,[weaponIdentifier] NSString *weaponIdentifier)
Definition Entity.m:991
instancetype explosionCloudFromEntity:withSize:andSettings:(Entity *entity,[withSize] float size,[andSettings] NSDictionary *settings)

Referenced by ShipDealEnergyDamage().

+ Here is the caller graph for this function:

◆ dealEnergyDamageWithinDesiredRange

- (void) dealEnergyDamageWithinDesiredRange

Definition at line 7616 of file ShipEntity.m.

8910{
8911 OOStandardsDeprecated([NSString stringWithFormat:@"dealEnergyDamageWithinDesiredRange is deprecated for %@",self]);
8912 // not over scannerRange
8913 NSArray* targets = [UNIVERSE entitiesWithinRange:(desired_range < SCANNER_MAX_RANGE ? desired_range : SCANNER_MAX_RANGE) ofEntity:self];
8914 if ([targets count] > 0)
8915 {
8916 unsigned i;
8917 for (i = 0; i < [targets count]; i++)
8918 {
8919 Entity *e2 = [targets objectAtIndex:i];
8920 Vector p2 = [self vectorTo:e2];
8921 double ecr = [e2 collisionRadius];
8922 double d = (magnitude(p2) - ecr) * 2.6; // 2.6 is a correction constant to stay in limits of the old code.
8923 double damage = (d > 0) ? weapon_damage * desired_range / (d * d) : weapon_damage;
8924 [e2 takeEnergyDamage:damage from:self becauseOf:[self owner] weaponIdentifier:[self primaryRole]];
8925 }
8926 }
8927}
void OOStandardsDeprecated(NSString *message)

◆ dealloc

- (void) dealloc
implementation

Reimplemented from OOEntityWithDrawable.

Reimplemented in DockEntity, PlayerEntity, and StationEntity.

Definition at line 14942 of file ShipEntity.m.

1074{
1075 /* NOTE: we guarantee that entityDestroyed is sent immediately after the
1076 JS ship becomes invalid (as a result of dropping the weakref), i.e.
1077 with no intervening script activity.
1078 It has to be after the invalidation so that scripts can't directly or
1079 indirectly cause the ship to become strong-referenced. (Actually, we
1080 could handle that situation by breaking out of dealloc, but that's a
1081 nasty abuse of framework semantics and would require special-casing in
1082 subclasses.)
1083 -- Ahruman 2011-02-27
1084 */
1085 [weakSelf weakRefDrop];
1086 weakSelf = nil;
1087 ShipScriptEventNoCx(self, "entityDestroyed");
1088
1089 [self setTrackCloseContacts:NO]; // deallocs tracking dictionary
1090 [[self parentEntity] subEntityReallyDied:self]; // Will do nothing if we're not really a subentity
1091 [self clearSubEntities];
1092
1095 DESTROY(shipAI);
1096 DESTROY(cargo);
1097 DESTROY(name);
1111 DESTROY(script);
1115 DESTROY(crew);
1117 DESTROY(octree);
1120
1125
1127
1128 [self setSubEntityTakingDamage:nil];
1129 [self removeAllEquipment];
1130
1131 [_group removeShip:self];
1132 DESTROY(_group);
1133 [_escortGroup removeShip:self];
1135
1137
1141
1143
1144 [super dealloc];
1145}
#define ShipScriptEventNoCx(ship, event,...)
OOWeakReference * weakSelf
OOColor * laser_color
Definition ShipEntity.h:229
OOColor * scanner_display_color_hostile2
Definition ShipEntity.h:235
NSDictionary * shipinfoDictionary
Definition ShipEntity.h:217
NSString * primaryRole
Definition ShipEntity.h:333
OOColor * scanner_display_color2
Definition ShipEntity.h:233
NSString * name
Definition ShipEntity.h:327
NSArray * portWeaponOffset
Definition ShipEntity.h:395
NSString * shipClassName
Definition ShipEntity.h:329
OOShipGroup * _group
Definition ShipEntity.h:466
OOWeakReference * _lastAegisLock
Definition ShipEntity.h:464
NSArray * starboardWeaponOffset
Definition ShipEntity.h:396
NSString * scan_description
Definition ShipEntity.h:331
NSString * shipUniqueName
Definition ShipEntity.h:328
OOColor * exhaust_emissive_color
Definition ShipEntity.h:231
NSArray * aftWeaponOffset
Definition ShipEntity.h:394
NSArray * forwardWeaponOffset
Definition ShipEntity.h:393
OOColor * scanner_display_color1
Definition ShipEntity.h:232
OOJSScript * script
Definition ShipEntity.h:222
OOColor * default_laser_color
Definition ShipEntity.h:230
OOJSScript * aiScript
Definition ShipEntity.h:223
OOColor * scanner_display_color_hostile1
Definition ShipEntity.h:234
NSString * displayName
Definition ShipEntity.h:330
NSString * lastRadioMessage
Definition ShipEntity.h:404
NSString * _shipKey
Definition ShipEntity.h:459

◆ dealMomentumWithinDesiredRange:

- (void) dealMomentumWithinDesiredRange: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8930 :(double)amount
8931{
8932 NSArray* targets = [UNIVERSE entitiesWithinRange:desired_range ofEntity:self];
8933 if ([targets count] > 0)
8934 {
8935 unsigned i;
8936 for (i = 0; i < [targets count]; i++)
8937 {
8938 ShipEntity *e2 = (ShipEntity*)[targets objectAtIndex:i];
8939 if ([e2 isShip] && [e2 isInSpace])
8940 {
8941 Vector p2 = [self vectorTo:e2];
8942 double ecr = [e2 collisionRadius];
8943 double d2 = magnitude2(p2) - ecr * ecr;
8944 // limit momentum transfer to relatively sensible levels
8945 if (d2 < 0.1)
8946 {
8947 d2 = 0.1;
8948 }
8949 double moment = amount*desired_range/d2;
8950 [e2 addImpactMoment:vector_normal(p2) fraction:moment];
8951 }
8952 }
8953 }
8954}
BOOL isInSpace()
Definition Entity.m:1134
void addImpactMoment:fraction:(Vector moment,[fraction] GLfloat howmuch)

◆ debugDumpPendingMessages

- (void) debugDumpPendingMessages
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

887{
888 [shipAI debugDumpPendingMessages];
889}

◆ decrease_flight_pitch:

- (void) decrease_flight_pitch: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8672 :(double) delta
8673{
8674 flightPitch -= delta;
8677 else if (flightPitch < -max_flight_pitch)
8679}

Referenced by PlayerShipSetProperty().

+ Here is the caller graph for this function:

◆ decrease_flight_roll:

- (void) decrease_flight_roll: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8652 :(double) delta
8653{
8654 flightRoll -= delta;
8657 else if (flightRoll < -max_flight_roll)
8659}

Referenced by PlayerShipSetProperty().

+ Here is the caller graph for this function:

◆ decrease_flight_speed:

- (void) decrease_flight_speed: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8623 :(double) delta
8624{
8625 double factor = 1.0;
8627 {
8628 factor = MIN_HYPERSPEED_FACTOR;
8629 }
8630
8631 if (flightSpeed > factor * delta)
8632 {
8633 flightSpeed -= factor * delta;
8634 }
8635 else
8636 {
8637 flightSpeed = 0;
8638 }
8639}
#define MIN_HYPERSPEED_FACTOR

◆ decrease_flight_yaw:

- (void) decrease_flight_yaw: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8692 :(double) delta
8693{
8694 flightYaw -= delta;
8697 else if (flightYaw < -max_flight_yaw)
8699}

Referenced by PlayerShipSetProperty().

+ Here is the caller graph for this function:

◆ defenseTargetCount

- (NSUInteger) defenseTargetCount

Definition at line 9589 of file ShipEntity.m.

11154{
11155 return [_defenseTargets count];
11156}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ defenseTargetEnumerator

- (NSEnumerator *) defenseTargetEnumerator

Definition at line 9589 of file ShipEntity.m.

11166{
11167 return [_defenseTargets objectEnumerator];
11168}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ deployEscorts

- (void) deployEscorts

Definition at line 9589 of file ShipEntity.m.

13832{
13833 ShipEntity *escort = nil;
13834 ShipEntity *target = nil;
13835 NSMutableSet *idleEscorts = nil;
13836 unsigned deployCount;
13837
13838 if ([self primaryTarget] == nil || _escortGroup == nil) return;
13839
13840 OOShipGroup *escortGroup = [self escortGroup];
13841 NSUInteger escortCount = [escortGroup count] - 1; // escorts minus leader.
13842 if (escortCount == 0) return;
13843
13844 if ([self group] == nil) [self setGroup:escortGroup];
13845
13846 if ([self primaryTarget] == [self lastEscortTarget])
13847 {
13848 // already deployed escorts onto this target!
13849 return;
13850 }
13851
13852 [self setLastEscortTarget:[self primaryTarget]];
13853
13854 // Find idle escorts
13855 idleEscorts = [NSMutableSet set];
13856 foreach (escort, [self escortEnumerator])
13857 {
13858 if (![[[escort getAI] name] isEqualToString:@"interceptAI.plist"] && ![escort hasNewAI])
13859 {
13860 [idleEscorts addObject:escort];
13861 }
13862 else if ([escort hasNewAI])
13863 {
13864 // JS-based escorts get a help request
13865 [escort doScriptEvent:OOJSID("helpRequestReceived") withArgument:self andArgument:[self primaryTarget]];
13866 }
13867 }
13868
13869 escortCount = [idleEscorts count];
13870 if (escortCount == 0) return;
13871
13872 deployCount = ranrot_rand() % escortCount + 1;
13873
13874 // Deploy deployCount idle escorts.
13875 target = [self primaryTarget];
13876 foreach (escort, idleEscorts)
13877 {
13878 [escort addTarget:target];
13879 [escort setAITo:@"interceptAI.plist"];
13880 [escort doScriptEvent:OOJSID("escortAttack") withArgument:target];
13881
13882 if (--deployCount == 0) break;
13883 }
13884
13885 [self updateEscortFormation];
13886}
void addTarget:(Entity *targetEntity)
NSEnumerator * escortEnumerator()
BOOL hasNewAI()
void setAITo:(NSString *aiString)
Entity * lastEscortTarget()

Referenced by ShipDeployEscorts().

+ Here is the caller graph for this function:

◆ descriptionComponents

- (NSString *) descriptionComponents
implementation

Reimplemented from Entity.

Reimplemented in StationEntity.

Definition at line 14942 of file ShipEntity.m.

1182{
1183 if (![self isSubEntity])
1184 {
1185 return [NSString stringWithFormat:@"\"%@\" %@", [self name], [super descriptionComponents]];
1186 }
1187 else
1188 {
1189 // ID, scanClass and status are of no interest for subentities.
1190 NSString *subtype = nil;
1191 if ([self behaviour] == BEHAVIOUR_TRACK_AS_TURRET) subtype = @"(turret)";
1192 else subtype = @"(subentity)";
1193
1194 return [NSString stringWithFormat:@"\"%@\" position: %@ %@", [self name], HPVectorDescription([self position]), subtype];
1195 }
1196}

◆ descriptionForObjDump

- (NSString *) descriptionForObjDump
implementation

Reimplemented from Entity.

Definition at line 14062 of file ShipEntity.m.

14830{
14831 NSString *desc = [super descriptionForObjDump];
14832 desc = [NSString stringWithFormat:@"%@ mass %g", desc, [self mass]];
14833 if (![self isPlayer])
14834 {
14835 desc = [NSString stringWithFormat:@"%@ AI: %@", desc, [[self getAI] shortDescriptionComponents]];
14836 }
14837 return desc;
14838}

◆ deserializeShipSubEntitiesFrom:

- (void) deserializeShipSubEntitiesFrom: (NSString *)  string

Definition at line 14942 of file ShipEntity.m.

833 :(NSString *)string
834{
835 NSArray *subEnts = [[self shipSubEntityEnumerator] allObjects];
836 NSInteger i,idx, start = [subEnts count] - 1;
837 NSInteger strMaxIdx = [string length] - 1;
838
839 ShipEntity *se = nil;
840
841 for (i = start; i >= 0; i--)
842 {
843 se = (ShipEntity *)[subEnts objectAtIndex:i];
844 idx = [se subIdx]; // should be identical to i, but better safe than sorry...
845 if (idx <= strMaxIdx && [[string substringWithRange:NSMakeRange(idx, 1)] isEqualToString:@"0"])
846 {
847 [se setSuppressExplosion:NO];
848 [se setEnergy:1];
849 [se takeEnergyDamage:500000000.0 from:nil becauseOf:nil weaponIdentifier:@""];
850 }
851 }
852}
void setEnergy:(GLfloat amount)
Definition Entity.m:812
void takeEnergyDamage:from:becauseOf:weaponIdentifier:(double amount, [from] Entity *ent, [becauseOf] Entity *other, [weaponIdentifier] NSString *weaponIdentifier)
NSUInteger subIdx()
Definition ShipEntity.m:786

◆ desiredRange

- (double) desiredRange

Definition at line 7616 of file ShipEntity.m.

8594{
8595 return desired_range;
8596}

◆ desiredSpeed

- (double) desiredSpeed

Definition at line 7616 of file ShipEntity.m.

8588{
8589 return desired_speed;
8590}

◆ destination

- (HPVector) destination

Definition at line 9589 of file ShipEntity.m.

10255{
10256 return _destination;
10257}

◆ destinationSystem

- (OOSystemID) destinationSystem

Definition at line 7616 of file ShipEntity.m.

7909{
7910 return destination_system;
7911}
OOSystemID destination_system
Definition ShipEntity.h:380

◆ disengageAutopilot

- (void) disengageAutopilot
implementation

Reimplemented in PlayerEntity.

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1636{
1637 OOLogERR(@"ai.invalid.notPlayer", @"Error in %@:%@, AI method endAutoPilot is only applicable to the player.", [shipAI name], [shipAI state]);
1638}
#define OOLogERR(class, format,...)
Definition OOLogging.h:112

◆ displayName

- (NSString *) displayName

◆ distance_six:

- (HPVector) distance_six: (GLfloat)  dist

Definition at line 9589 of file ShipEntity.m.

10269 : (GLfloat) dist
10270{
10271 HPVector six = position;
10272 six.x -= dist * v_forward.x; six.y -= dist * v_forward.y; six.z -= dist * v_forward.z;
10273 return six;
10274}

◆ distance_twelve:withOffset:

- (HPVector) distance_twelve: (GLfloat)  dist
withOffset: (GLfloat)  offset 

Definition at line 9589 of file ShipEntity.m.

10277 : (GLfloat) dist withOffset:(GLfloat)offset
10278{
10279 HPVector twelve = position;
10280 twelve.x += dist * v_up.x; twelve.y += dist * v_up.y; twelve.z += dist * v_up.z;
10281 twelve.x += offset * v_right.x; twelve.y += offset * v_right.y; twelve.z += offset * v_right.z;
10282 return twelve;
10283}

◆ dockEscorts

- (void) dockEscorts

Definition at line 9589 of file ShipEntity.m.

13891{
13892 if (![self hasEscorts]) return;
13893
13894 OOShipGroup *escortGroup = [self escortGroup];
13895 ShipEntity *escort = nil;
13896 ShipEntity *target = [self primaryTarget];
13897 unsigned i = 0;
13898 // Note: works on escortArray rather than escortEnumerator because escorts may be mutated.
13899 foreach (escort, [self escortArray])
13900 {
13901 float delay = i++ * 3.0 + 1.5; // send them off at three second intervals
13902 AI *ai = [escort getAI];
13903
13904 // act individually now!
13905 if ([escort group] == escortGroup) [escort setGroup:nil];
13906 if ([escort owner] == self) [escort setOwner:escort];
13907 if(target && [target isStation]) [escort setTargetStation:target];
13908 // JSAI: handles own delay
13909 if (![escort hasNewAI])
13910 {
13911 [escort setAITo:@"dockingAI.plist"];
13912 [ai setState:@"ABORT" afterDelay:delay + 0.25];
13913 }
13914 [escort doScriptEvent:OOJSID("escortDock") withArgument:[NSNumber numberWithFloat:delay]];
13915 }
13916
13917 // We now have no escorts.
13918 [_escortGroup release];
13919 _escortGroup = nil;
13920}
Definition AI.h:38
void setState:afterDelay:(NSString *stateName,[afterDelay] NSTimeInterval delay)
Definition AI.m:358
void setTargetStation:(Entity *targetEntity)

Referenced by ShipDockEscorts().

+ Here is the caller graph for this function:

◆ dockingInstructions

- (NSDictionary *) dockingInstructions

◆ doesHitLine:v0:

- (GLfloat) doesHitLine: (HPVector) 
v0: (HPVector)  v1 

Definition at line 14942 of file ShipEntity.m.

1442 :(HPVector)v0 :(HPVector)v1
1443{
1444 Vector u0 = HPVectorToVector(HPvector_between(position, v0)); // relative to origin of model / octree
1445 Vector u1 = HPVectorToVector(HPvector_between(position, v1));
1446 Vector w0 = make_vector(dot_product(u0, v_right), dot_product(u0, v_up), dot_product(u0, v_forward)); // in ijk vectors
1447 Vector w1 = make_vector(dot_product(u1, v_right), dot_product(u1, v_up), dot_product(u1, v_forward));
1448 return [octree isHitByLine:w0 :w1];
1449}

◆ doesHitLine:v0:v1:

- (GLfloat) doesHitLine: (HPVector) 
v0: (HPVector) 
v1: (ShipEntity**)  hitEntity 

Reimplemented in PlayerEntity.

Definition at line 14942 of file ShipEntity.m.

1452 :(HPVector)v0 :(HPVector)v1 :(ShipEntity **)hitEntity
1453{
1454 if (hitEntity)
1455 hitEntity[0] = (ShipEntity*)nil;
1456 Vector u0 = HPVectorToVector(HPvector_between(position, v0)); // relative to origin of model / octree
1457 Vector u1 = HPVectorToVector(HPvector_between(position, v1));
1458 Vector w0 = make_vector(dot_product(u0, v_right), dot_product(u0, v_up), dot_product(u0, v_forward)); // in ijk vectors
1459 Vector w1 = make_vector(dot_product(u1, v_right), dot_product(u1, v_up), dot_product(u1, v_forward));
1460 GLfloat hit_distance = [octree isHitByLine:w0 :w1];
1461 if (hit_distance)
1462 {
1463 if (hitEntity)
1464 hitEntity[0] = self;
1465 }
1466
1467 NSEnumerator *subEnum = nil;
1468 ShipEntity *se = nil;
1469 for (subEnum = [self shipSubEntityEnumerator]; (se = [subEnum nextObject]); )
1470 {
1471 HPVector p0 = [se absolutePositionForSubentity];
1472 Triangle ijk = [se absoluteIJKForSubentity];
1473 u0 = HPVectorToVector(HPvector_between(p0, v0));
1474 u1 = HPVectorToVector(HPvector_between(p0, v1));
1475 w0 = resolveVectorInIJK(u0, ijk);
1476 w1 = resolveVectorInIJK(u1, ijk);
1477
1478 GLfloat hitSub = [se->octree isHitByLine:w0 :w1];
1479 if (hitSub && (hit_distance == 0 || hit_distance > hitSub))
1480 {
1481 hit_distance = hitSub;
1482 if (hitEntity)
1483 {
1484 *hitEntity = se;
1485 }
1486 }
1487 }
1488
1489 return hit_distance;
1490}
Triangle absoluteIJKForSubentity()

◆ doesHitLine:v0:withPosition:andIJK:i:j:

- (GLfloat) doesHitLine: (HPVector) 
v0: (HPVector)  v1
withPosition: (HPVector)  o
andIJK: (Vector) 
i: (Vector) 
j: (Vector)  k 

Definition at line 14942 of file ShipEntity.m.

1493 :(HPVector)v0 :(HPVector)v1 withPosition:(HPVector)o andIJK:(Vector)i :(Vector)j :(Vector)k
1494{
1495 Vector u0 = HPVectorToVector(HPvector_between(o, v0)); // relative to origin of model / octree
1496 Vector u1 = HPVectorToVector(HPvector_between(o, v1));
1497 Vector w0 = make_vector(dot_product(u0, i), dot_product(u0, j), dot_product(u0, k)); // in ijk vectors
1498 Vector w1 = make_vector(dot_product(u1, j), dot_product(u1, j), dot_product(u1, k));
1499 return [octree isHitByLine:w0 :w1];
1500}

◆ doNothing

- (void) doNothing
implementation

Definition at line 14062 of file ShipEntity.m.

14823{
14824
14825}

◆ doOctreesCollide

- (ShipEntity *) doOctreesCollide (ShipEntity *)  prime
(ShipEntity *)  other 
implementation

Definition at line 2092 of file ShipEntity.m.

2093{
2094 // octree check
2095 Octree *prime_octree = prime->octree;
2096 Octree *other_octree = other->octree;
2097
2098 HPVector prime_position = [prime absolutePositionForSubentity];
2099 Triangle prime_ijk = [prime absoluteIJKForSubentity];
2100 HPVector other_position = [other absolutePositionForSubentity];
2101 Triangle other_ijk = [other absoluteIJKForSubentity];
2102
2103 Vector relative_position_of_other = resolveVectorInIJK(HPVectorToVector(HPvector_between(prime_position, other_position)), prime_ijk);
2104 Triangle relative_ijk_of_other;
2105 relative_ijk_of_other.v[0] = resolveVectorInIJK(other_ijk.v[0], prime_ijk);
2106 relative_ijk_of_other.v[1] = resolveVectorInIJK(other_ijk.v[1], prime_ijk);
2107 relative_ijk_of_other.v[2] = resolveVectorInIJK(other_ijk.v[2], prime_ijk);
2108
2109 // check hull octree against other hull octree
2110 if ([prime_octree isHitByOctree:other_octree
2111 withOrigin:relative_position_of_other
2112 andIJK:relative_ijk_of_other])
2113 {
2114 return other;
2115 }
2116
2117 // check prime subentities against the other's hull
2118 NSArray *prime_subs = prime->subEntities;
2119 if (prime_subs)
2120 {
2121 NSUInteger i, n_subs = [prime_subs count];
2122 for (i = 0; i < n_subs; i++)
2123 {
2124 Entity* se = [prime_subs objectAtIndex:i];
2125 if ([se isShip] && [se canCollide] && doOctreesCollide((ShipEntity*)se, other))
2126 return other;
2127 }
2128 }
2129
2130 // check prime hull against the other's subentities
2131 NSArray *other_subs = other->subEntities;
2132 if (other_subs)
2133 {
2134 NSUInteger i, n_subs = [other_subs count];
2135 for (i = 0; i < n_subs; i++)
2136 {
2137 Entity* se = [other_subs objectAtIndex:i];
2138 if ([se isShip] && [se canCollide] && doOctreesCollide(prime, (ShipEntity*)se))
2139 return (ShipEntity*)se;
2140 }
2141 }
2142
2143 // check prime subenties against the other's subentities
2144 if ((prime_subs)&&(other_subs))
2145 {
2146 NSUInteger i, n_osubs = [other_subs count];
2147 for (i = 0; i < n_osubs; i++)
2148 {
2149 Entity* oe = [other_subs objectAtIndex:i];
2150 if ([oe isShip] && [oe canCollide])
2151 {
2152 NSUInteger j, n_psubs = [prime_subs count];
2153 for (j = 0; j < n_psubs; j++)
2154 {
2155 Entity* pe = [prime_subs objectAtIndex:j];
2156 if ([pe isShip] && [pe canCollide] && doOctreesCollide((ShipEntity*)pe, (ShipEntity*)oe))
2157 return (ShipEntity*)oe;
2158 }
2159 }
2160 }
2161 }
2162
2163 // fall through => no collision
2164 return nil;
2165}
static BOOL isHitByOctree(Octree_details axialDetails, Octree_details otherDetails, Vector delta, Triangle other_ijk)
BOOL canCollide()

◆ doScriptEvent:

- (void) doScriptEvent: (jsid)  message

Definition at line 14062 of file ShipEntity.m.

14618 :(jsid)message
14619{
14620 JSContext *context = OOJSAcquireContext();
14621 [self doScriptEvent:message inContext:context withArguments:NULL count:0];
14622 OOJSRelinquishContext(context);
14623}

◆ doScriptEvent:andReactToAIMessage:

- (void) doScriptEvent: (jsid)  scriptEvent
andReactToAIMessage: (NSString *)  aiMessage 

Definition at line 14062 of file ShipEntity.m.

14716 :(jsid)scriptEvent andReactToAIMessage:(NSString *)aiMessage
14717{
14718 [self doScriptEvent:scriptEvent];
14719 [self reactToAIMessage:aiMessage context:nil];
14720}

◆ doScriptEvent:inContext:withArguments:count:

- (void) doScriptEvent: (jsid)  message
inContext: (JSContext *)  context
withArguments: (jsval *)  argv
count: (uintN)  argc 

Reimplemented in PlayerEntity.

Definition at line 14062 of file ShipEntity.m.

14696 :(jsid)message inContext:(JSContext *)context withArguments:(jsval *)argv count:(uintN)argc
14697{
14698 // This method is a bottleneck so that PlayerEntity can override at one point.
14699 [script callMethod:message inContext:context withArguments:argv count:argc result:NULL];
14700 [aiScript callMethod:message inContext:context withArguments:argv count:argc result:NULL];
14701}

◆ doScriptEvent:withArgument:

- (void) doScriptEvent: (jsid)  message
withArgument: (id)  argument 

Definition at line 14062 of file ShipEntity.m.

14626 :(jsid)message withArgument:(id)argument
14627{
14628 JSContext *context = OOJSAcquireContext();
14629
14630 jsval value = OOJSValueFromNativeObject(context, argument);
14631 [self doScriptEvent:message inContext:context withArguments:&value count:1];
14632
14633 OOJSRelinquishContext(context);
14634}
OOINLINE jsval OOJSValueFromNativeObject(JSContext *context, id object)

Referenced by PlayerReplaceShip(), PlayerShipSetProperty(), ShipAwardEquipment(), ShipRemove(), and ShipSetEquipmentStatus().

+ Here is the caller graph for this function:

◆ doScriptEvent:withArgument:andArgument:

- (void) doScriptEvent: (jsid)  message
withArgument: (id)  argument1
andArgument: (id)  argument2 

Definition at line 14062 of file ShipEntity.m.

14637 :(jsid)message
14638 withArgument:(id)argument1
14639 andArgument:(id)argument2
14640{
14641 JSContext *context = OOJSAcquireContext();
14642
14643 jsval argv[2] = { OOJSValueFromNativeObject(context, argument1), OOJSValueFromNativeObject(context, argument2) };
14644 [self doScriptEvent:message inContext:context withArguments:argv count:2];
14645
14646 OOJSRelinquishContext(context);
14647}

Referenced by PlayerReplaceShip().

+ Here is the caller graph for this function:

◆ doScriptEvent:withArgument:andReactToAIMessage:

- (void) doScriptEvent: (jsid)  scriptEvent
withArgument: (id)  argument
andReactToAIMessage: (NSString *)  aiMessage 

Definition at line 14062 of file ShipEntity.m.

14723 :(jsid)scriptEvent withArgument:(id)argument andReactToAIMessage:(NSString *)aiMessage
14724{
14725 [self doScriptEvent:scriptEvent withArgument:argument];
14726 [self reactToAIMessage:aiMessage context:nil];
14727}

◆ doScriptEvent:withArguments:

- (void) doScriptEvent: (jsid)  message
withArguments: (NSArray *)  arguments 

Definition at line 14062 of file ShipEntity.m.

14650 :(jsid)message withArguments:(NSArray *)arguments
14651{
14652 JSContext *context = OOJSAcquireContext();
14653 uintN i, argc;
14654 jsval *argv = NULL;
14655
14656 // Convert arguments to JS values and make them temporarily un-garbage-collectable.
14657 argc = (uintN)[arguments count];
14658 if (argc != 0)
14659 {
14660 argv = malloc(sizeof *argv * argc);
14661 if (argv != NULL)
14662 {
14663 for (i = 0; i != argc; ++i)
14664 {
14665 argv[i] = [[arguments objectAtIndex:i] oo_jsValueInContext:context];
14666 OOJSAddGCValueRoot(context, &argv[i], "event parameter");
14667 }
14668 }
14669 else argc = 0;
14670 }
14671
14672 [self doScriptEvent:message inContext:context withArguments:argv count:argc];
14673
14674 // Re-garbage-collectibalize the arguments and free the array.
14675 if (argv != NULL)
14676 {
14677 for (i = 0; i != argc; ++i)
14678 {
14679 JS_RemoveValueRoot(context, &argv[i]);
14680 }
14681 free(argv);
14682 }
14683
14684 OOJSRelinquishContext(context);
14685}
#define OOJSAddGCValueRoot(context, root, name)

◆ doScriptEvent:withArguments:count:

- (void) doScriptEvent: (jsid)  message
withArguments: (jsval *)  argv
count: (uintN)  argc 

Definition at line 14062 of file ShipEntity.m.

14688 :(jsid)message withArguments:(jsval *)argv count:(uintN)argc
14689{
14690 JSContext *context = OOJSAcquireContext();
14691 [self doScriptEvent:message inContext:context withArguments:argv count:argc];
14692 OOJSRelinquishContext(context);
14693}

◆ drawDebugStuff

- (void) drawDebugStuff
implementation

Provided by category ShipEntity(Private).

Definition at line 2092 of file ShipEntity.m.

6425{
6426 // HPVect: imprecise here - needs camera relative
6427 if (0 && reportAIMessages)
6428 {
6429 OODebugDrawPoint(HPVectorToVector(_destination), [OOColor blueColor]);
6430 OODebugDrawColoredLine(HPVectorToVector([self position]), HPVectorToVector(_destination), [OOColor colorWithWhite:0.15 alpha:1.0]);
6431
6432 Entity *pTarget = [self primaryTarget];
6433 if (pTarget != nil)
6434 {
6435 OODebugDrawPoint(HPVectorToVector([pTarget position]), [OOColor redColor]);
6436 OODebugDrawColoredLine(HPVectorToVector([self position]), HPVectorToVector([pTarget position]), [OOColor colorWithRed:0.2 green:0.0 blue:0.0 alpha:1.0]);
6437 }
6438
6439 Entity *sTarget = [self targetStation];
6440 if (sTarget != pTarget && [sTarget isStation])
6441 {
6442 OODebugDrawPoint(HPVectorToVector([sTarget position]), [OOColor cyanColor]);
6443 }
6444
6445 Entity *fTarget = [self foundTarget];
6446 if (fTarget != nil && fTarget != pTarget && fTarget != sTarget)
6447 {
6448 OODebugDrawPoint(HPVectorToVector([fTarget position]), [OOColor magentaColor]);
6449 }
6450 }
6451}
void OODebugDrawColoredLine(Vector start, Vector end, OOColor *color)
void OODebugDrawPoint(Vector position, OOColor *color)
unsigned reportAIMessages
Definition ShipEntity.h:255

◆ drawImmediate:translucent:

- (void) drawImmediate: (bool)  immediate
translucent: (bool)  translucent 
implementation

Reimplemented from OOEntityWithDrawable.

Reimplemented in DockEntity, and PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

6383 :(bool)immediate translucent:(bool)translucent
6384{
6385 if ((no_draw_distance < cam_zero_distance) || // Done redundantly to skip subentities
6386 (cloaking_device_active && randf() > 0.10))
6387 {
6388 // Don't draw.
6389 return;
6390 }
6391
6392 // Draw self.
6393 [super drawImmediate:immediate translucent:translucent];
6394
6395#ifndef NDEBUG
6396 // Draw bounding boxes if we have to before going for the subentities.
6397 // TODO: the translucent flag here makes very little sense. Something's wrong with the matrices.
6398 if (translucent) [self drawDebugStuff];
6399 else if (gDebugFlags & DEBUG_BOUNDING_BOXES && ![self isSubEntity])
6400 {
6403 }
6404#endif
6405
6406 // Draw subentities.
6407 if (!immediate) // TODO: is this relevant any longer?
6408 {
6409 // save time by not copying the subentity array if it's empty - CIM
6410 if ([self subEntityCount] > 0)
6411 {
6412 Entity<OOSubEntity> *subEntity = nil;
6413 foreach (subEntity, [self subEntities])
6414 {
6415 NSAssert3([subEntity owner] == self, @"Subentity ownership broke - %@ should be owned by %@ but is owned by %@.", subEntity, self, [subEntity owner]);
6416 [subEntity drawSubEntityImmediate:immediate translucent:translucent];
6417 }
6418 }
6419 }
6420}
NSUInteger gDebugFlags
Definition main.m:7
@ DEBUG_BOUNDING_BOXES
OOINLINE void OODebugDrawColoredBoundingBox(BoundingBox box, OOColor *color)
OOINLINE void OODebugDrawBoundingBox(BoundingBox box)
void drawSubEntityImmediate:translucent:(bool immediate, [translucent] bool translucent)
GLfloat cam_zero_distance
Definition Entity.h:109
GLfloat no_draw_distance
Definition Entity.h:110
BoundingBox totalBoundingBox
Definition ShipEntity.h:213
NSUInteger subEntityCount()

◆ drawSubEntityImmediate:translucent:

- (void) drawSubEntityImmediate: (bool)  immediate
translucent: (bool)  translucent 
implementation

Reimplemented from Entity.

Definition at line 2092 of file ShipEntity.m.

6455 :(bool)immediate translucent:(bool)translucent
6456{
6458
6459 if (cam_zero_distance > no_draw_distance) // this test provides an opportunity to do simple LoD culling
6460 {
6461 return; // TOO FAR AWAY
6462 }
6464
6465 // HPVect: need to make camera-relative
6466 OOGLTranslateModelView(HPVectorToVector(position));
6468 [self drawImmediate:immediate translucent:translucent];
6469
6470#ifndef NDEBUG
6472 {
6474 }
6475#endif
6476
6478
6480}
void OOGLPushModelView(void)
void OOGLTranslateModelView(Vector vector)
void OOGLMultModelView(OOMatrix matrix)
OOMatrix OOGLPopModelView(void)
#define OOVerifyOpenGLState()
Definition OOOpenGL.h:136
OOMatrix rotMatrix
Definition Entity.h:138

◆ dropMessages:

- (void) dropMessages: (NSString *)  messageString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

872 :(NSString *)messageString
873{
874 NSArray *messages = nil;
875 NSString *message = nil;
876 NSCharacterSet *whiteSpace = [NSCharacterSet whitespaceCharacterSet];
877
878 messages = [messageString componentsSeparatedByString:@","];
879 foreach (message, messages)
880 {
881 [shipAI dropMessage:[message stringByTrimmingCharactersInSet:whiteSpace]];
882 }
883}

◆ dumpCargo

- (OOCommodityType) dumpCargo

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12481{
12482 ShipEntity *jetto = [self dumpCargoItem:nil];
12483 if (jetto != nil)
12484 {
12485 return [jetto commodityType];
12486 }
12487 else
12488 {
12489 return nil;
12490 }
12491}

◆ dumpCargoItem:

- (ShipEntity *) dumpCargoItem: (OOCommodityType preferred

Definition at line 9589 of file ShipEntity.m.

12494 :(OOCommodityType)preferred
12495{
12496 ShipEntity *jetto = nil;
12497 NSUInteger i = 0;
12498
12499 if (([cargo count] > 0)&&([UNIVERSE getTime] - cargo_dump_time > 0.5)) // space them 0.5s or 10m apart
12500 {
12501 if (preferred == nil)
12502 {
12503 jetto = [[[cargo objectAtIndex:0] retain] autorelease];
12504 }
12505 else
12506 {
12507 BOOL found = NO;
12508 for (i=0;i<[cargo count];i++)
12509 {
12510 if ([[[cargo objectAtIndex:i] commodityType] isEqualToString:preferred])
12511 {
12512 jetto = [[[cargo objectAtIndex:i] retain] autorelease];
12513 found = YES;
12514 break;
12515 }
12516 }
12517 if (found == NO)
12518 {
12519 // dump anything
12520 jetto = [[[cargo objectAtIndex:0] retain] autorelease];
12521 i = 0;
12522 }
12523 }
12524 if (jetto != nil)
12525 {
12526 [self dumpItem:jetto]; // CLASS_CARGO, STATUS_IN_FLIGHT, AI state GLOBAL
12527 [cargo removeObjectAtIndex:i];
12528 [self broadcastAIMessage:@"CARGO_DUMPED"]; // goes only to 16 nearby ships in range, but that should be enough.
12529 unsigned i;
12530 // only send script event to powered entities
12531 [self checkScannerIgnoringUnpowered];
12532 for (i = 0; i < n_scanned_ships ; i++)
12533 {
12534 ShipEntity* other = scanned_ships[i];
12535 [other doScriptEvent:OOJSID("cargoDumpedNearby") withArgument:jetto andArgument:self];
12536
12537 }
12538 }
12539 }
12540
12541 return jetto;
12542}
OOTimeAbsolute cargo_dump_time
Definition ShipEntity.h:358

◆ dumpItem:

- (OOCargoType) dumpItem: (ShipEntity*)  jetto

Definition at line 9589 of file ShipEntity.m.

12545 : (ShipEntity*) cargoObj
12546{
12547 if (!cargoObj)
12548 return 0;
12549
12550 ShipEntity* jetto = [UNIVERSE reifyCargoPod:cargoObj];
12551
12552 int result = [jetto cargoType];
12553 AI *jettoAI = nil;
12554 Vector start;
12555
12556 // players get to see their old ship sailing forth, while NPCs run away more efficiently!
12557 // cargo is ejected at higher speed from any ship
12558 double eject_speed = EXPECT_NOT([jetto crew] && [jetto isPlayer]) ? 20.0 : 100.0;
12559 double eject_reaction = -eject_speed * [jetto mass] / [self mass];
12560 double jcr = jetto->collision_radius;
12561
12562 Quaternion jetto_orientation = kIdentityQuaternion;
12563 Vector vel, v_eject, v_eject_normal;
12564 HPVector rpos = [self absolutePositionForSubentity];
12565 double jetto_roll = 0;
12566 double jetto_pitch = 0;
12567
12568 // default launching position
12569 start.x = 0.0; // in the middle
12570 start.y = 0.0; //
12571 start.z = boundingBox.min.z - jcr; // 1m behind of bounding box
12572
12573 // custom launching position
12574 start = [shipinfoDictionary oo_vectorForKey:@"aft_eject_position" defaultValue:start];
12575
12576 v_eject = vector_normal(start);
12577
12578 // check if start is within bounding box...
12579 while ( (start.x > boundingBox.min.x - jcr)&&(start.x < boundingBox.max.x + jcr)&&
12580 (start.y > boundingBox.min.y - jcr)&&(start.y < boundingBox.max.y + jcr)&&
12581 (start.z > boundingBox.min.z - jcr)&&(start.z < boundingBox.max.z + jcr))
12582 {
12583 start = vector_add(start, vector_multiply_scalar(v_eject, jcr));
12584 }
12585
12586 v_eject = quaternion_rotate_vector([self normalOrientation], start);
12587 rpos = HPvector_add(rpos, vectorToHPVector(v_eject));
12588 v_eject = vector_normal(v_eject);
12589 v_eject_normal = v_eject;
12590
12591 v_eject.x += (randf() - randf())/eject_speed;
12592 v_eject.y += (randf() - randf())/eject_speed;
12593 v_eject.z += (randf() - randf())/eject_speed;
12594
12595 vel = vector_add(vector_multiply_scalar(v_forward, flightSpeed), vector_multiply_scalar(v_eject, eject_speed));
12596 velocity = vector_add(velocity, vector_multiply_scalar(v_eject, eject_reaction));
12597
12598 [jetto setPosition:rpos];
12599 if ([jetto crew]) // jetto has a crew, so assume it is an escape pod.
12600 {
12601 // orient the pod away from the ship to avoid colliding with it.
12602 jetto_orientation = quaternion_rotation_between(v_eject_normal, kBasisZVector);
12603 }
12604 else
12605 {
12606 // It is true cargo, let it tumble.
12607 jetto_roll = ((ranrot_rand() % 1024) - 512.0)/1024.0; // -0.5 to +0.5
12608 jetto_pitch = ((ranrot_rand() % 1024) - 512.0)/1024.0; // -0.5 to +0.5
12609 quaternion_set_random(&jetto_orientation);
12610 }
12611
12612 [jetto setOrientation:jetto_orientation];
12613 [jetto setRoll:jetto_roll];
12614 [jetto setPitch:jetto_pitch];
12615 [jetto setVelocity:vel];
12616 [jetto setScanClass: CLASS_CARGO];
12617 [jetto setTemperature:[self randomEjectaTemperature]];
12618 [UNIVERSE addEntity:jetto]; // STATUS_IN_FLIGHT, AI state GLOBAL
12619
12620 jettoAI = [jetto getAI];
12621 if ([jettoAI hasSuspendedStateMachines]) // check if this was previous scooped cargo.
12622 {
12623 [jetto setThrust:[jetto maxThrust]]; // restore old thrust.
12624 [jetto setOwner:jetto];
12625 [jettoAI exitStateMachineWithMessage:nil]; // exit nullAI.
12626 }
12627 [jetto doScriptEvent:OOJSID("shipWasDumped") withArgument:self];
12628 [self doScriptEvent:OOJSID("shipDumpedCargo") withArgument:jetto];
12629
12630 cargo_dump_time = [UNIVERSE getTime];
12631 return result;
12632}
Quaternion quaternion_rotation_between(Vector v0, Vector v1)
float maxThrust()
void setRoll:(double amount)
void setThrust:(double amount)
void setPitch:(double amount)

Referenced by ShipEntity(ScriptMethods)::ejectShipOfRole:.

+ Here is the caller graph for this function:

◆ dumpSelfState

- (void) dumpSelfState
implementation

Reimplemented from Entity.

Reimplemented in PlayerEntity, and StationEntity.

Definition at line 14062 of file ShipEntity.m.

14489{
14490 NSMutableArray *flags = nil;
14491 NSString *flagsString = nil;
14492
14493 [super dumpSelfState];
14494
14495 OOLog(@"dumpState.shipEntity", @"Type: %@", [self shipDataKey]);
14496 OOLog(@"dumpState.shipEntity", @"Name: %@", name);
14497 OOLog(@"dumpState.shipEntity", @"Display Name: %@", [self displayName]);
14498 OOLog(@"dumpState.shipEntity", @"Roles: %@", [self roleSet]);
14499 OOLog(@"dumpState.shipEntity", @"Primary role: %@", primaryRole);
14500 OOLog(@"dumpState.shipEntity", @"Script: %@", script);
14501 OOLog(@"dumpState.shipEntity", @"Subentity count: %llu", [self subEntityCount]);
14502 OOLog(@"dumpState.shipEntity", @"Behaviour: %@", OOStringFromBehaviour(behaviour));
14503 id target = [self primaryTarget];
14504 if (target == nil) target = @"<none>";
14505 OOLog(@"dumpState.shipEntity", @"Target: %@", target);
14506 OOLog(@"dumpState.shipEntity", @"Destination: %@", HPVectorDescription(_destination));
14507 OOLog(@"dumpState.shipEntity", @"Other destination: %@", HPVectorDescription(coordinates));
14508 OOLog(@"dumpState.shipEntity", @"Waypoint count: %u", number_of_navpoints);
14509 OOLog(@"dumpState.shipEntity", @"Desired speed: %g", desired_speed);
14510 OOLog(@"dumpState.shipEntity", @"Thrust: %g", thrust);
14511 if ([self escortCount] != 0) OOLog(@"dumpState.shipEntity", @"Escort count: %u", [self escortCount]);
14512 OOLog(@"dumpState.shipEntity", @"Fuel: %i", fuel);
14513 OOLog(@"dumpState.shipEntity", @"Fuel accumulator: %g", fuel_accumulator);
14514 OOLog(@"dumpState.shipEntity", @"Missile count: %u", missiles);
14515
14516 if (shipAI != nil && OOLogWillDisplayMessagesInClass(@"dumpState.shipEntity.ai"))
14517 {
14518 OOLog(@"dumpState.shipEntity.ai", @"%@", @"AI:");
14520 OOLogIndent();
14521 @try
14522 {
14523 [shipAI dumpState];
14524 }
14525 @catch (id exception) {}
14527 }
14528 OOLog(@"dumpState.shipEntity", @"Accuracy: %g", accuracy);
14529 OOLog(@"dumpState.shipEntity", @"Jink position: %@", VectorDescription(jink));
14530 OOLog(@"dumpState.shipEntity", @"Frustration: %g", frustration);
14531 OOLog(@"dumpState.shipEntity", @"Success factor: %g", success_factor);
14532 OOLog(@"dumpState.shipEntity", @"Shots fired: %u", shot_counter);
14533 OOLog(@"dumpState.shipEntity", @"Time since shot: %g", [self shotTime]);
14534 OOLog(@"dumpState.shipEntity", @"Spawn time: %g (%g seconds ago)", [self spawnTime], [self timeElapsedSinceSpawn]);
14535 if ([self isBeacon])
14536 {
14537 OOLog(@"dumpState.shipEntity", @"Beacon code: %@", [self beaconCode]);
14538 }
14539 OOLog(@"dumpState.shipEntity", @"Hull temperature: %g", ship_temperature);
14540 OOLog(@"dumpState.shipEntity", @"Heat insulation: %g", [self heatInsulation]);
14541
14542 flags = [NSMutableArray array];
14543 #define ADD_FLAG_IF_SET(x) if (x) { [flags addObject:@#x]; }
14557 flagsString = [flags count] ? [flags componentsJoinedByString:@", "] : (NSString *)@"none";
14558 OOLog(@"dumpState.shipEntity", @"Flags: %@", flagsString);
14559}
#define ADD_FLAG_IF_SET(x)
void OOLogPushIndent(void)
Definition OOLogging.m:316
void OOLogPopIndent(void)
Definition OOLogging.m:340
BOOL OOLogWillDisplayMessagesInClass(NSString *inMessageClass)
Definition OOLogging.m:144
void OOLogIndent(void)
Definition OOLogging.m:366
NSString * OOStringFromBehaviour(OOBehaviour behaviour) CONST_FUNC
GLfloat timeElapsedSinceSpawn()
Definition Entity.m:1083
OOTimeAbsolute spawnTime
Definition Entity.h:150
NSString * shipDataKey()
unsigned being_fined
Definition ShipEntity.h:259
HPVector coordinates
Definition ShipEntity.h:339
BOOL isBeacon()
float ship_temperature
Definition ShipEntity.h:410
GLfloat heatInsulation()
unsigned military_jammer_active
Definition ShipEntity.h:249
int shot_counter
Definition ShipEntity.h:357
unsigned isHulk
Definition ShipEntity.h:261

◆ ejectCargo

- (void) ejectCargo
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1671{
1672 OOCargoQuantity i, cargo_to_go = 0.1 * [self maxAvailableCargoSpace];
1673 while (cargo_to_go > 15)
1674 {
1675 cargo_to_go = ranrot_rand() % cargo_to_go;
1676 }
1677 [self dumpCargo];
1678 for (i = 1; i < cargo_to_go; i++)
1679 {
1680 [self performSelector:@selector(dumpCargo) withObject:nil afterDelay:0.75 * i]; // drop 3 canisters per 2 seconds
1681 }
1682}

◆ ejectShipOfRole:

- (ShipEntity *) ejectShipOfRole: (NSString *)  role

Provided by category ShipEntity(ScriptMethods).

Definition at line 31 of file ShipEntityScriptMethods.m.

50 :(NSString *)role
51{
52 ShipEntity *item = nil;
53
54 if (role != nil)
55 {
56 item = [[UNIVERSE newShipWithRole:role] autorelease];
57 if (item != nil) [self dumpItem:item];
58 }
59
60 return item;
61}

◆ ejectShipOfType:

- (ShipEntity *) ejectShipOfType: (NSString *)  shipKey

Provided by category ShipEntity(ScriptMethods).

Definition at line 31 of file ShipEntityScriptMethods.m.

36 :(NSString *)shipKey
37{
38 ShipEntity *item = nil;
39
40 if (shipKey != nil)
41 {
42 item = [[UNIVERSE newShipWithName:shipKey] autorelease];
43 if (item != nil) [self dumpItem:item];
44 }
45
46 return item;
47}

◆ energyRechargeRate

- (float) energyRechargeRate

Definition at line 7408 of file ShipEntity.m.

7500{
7501 return energy_recharge_rate;
7502}

Referenced by OOShipLibraryGenerator().

+ Here is the caller graph for this function:

◆ enterDock:

- (void) enterDock: (StationEntity *)  station

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

13451 :(StationEntity *)station
13452{
13453 // throw these away now we're docked...
13454 if (dockingInstructions != nil)
13455 {
13456 [dockingInstructions autorelease];
13458 }
13459
13460 [self doScriptEvent:OOJSID("shipWillDockWithStation") withArgument:station];
13461 [self doScriptEvent:OOJSID("shipDockedWithStation") withArgument:station];
13462 [shipAI message:@"DOCKED"];
13463 [station noteDockedShip:self];
13464 [UNIVERSE removeEntity:self];
13465}
void noteDockedShip:(ShipEntity *ship)

◆ enterPlayerWormhole

- (void) enterPlayerWormhole

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

633{
634 [self enterWormhole:[PLAYER wormhole] replacing:NO];
635}

◆ enterTargetWormhole

- (void) enterTargetWormhole

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

638{
639 WormholeEntity *whole = nil;
640 ShipEntity *targEnt = [self primaryTarget];
641 double found_d2 = scannerRange * scannerRange;
642
643 if (targEnt && (HPdistance2(position, [targEnt position]) < found_d2))
644 {
645 if ([targEnt isWormhole])
646 whole = (WormholeEntity *)targEnt;
647 else if ([targEnt isPlayer])
648 whole = [PLAYER wormhole];
649 }
650
651 if (!whole)
652 {
653 // locate nearest wormhole
654 int ent_count = UNIVERSE->n_entities;
655 Entity** uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
656 WormholeEntity* wormholes[ent_count];
657 int i;
658 int wh_count = 0;
659 for (i = 0; i < ent_count; i++)
660 if (uni_entities[i]->isWormhole)
661 wormholes[wh_count++] = [(WormholeEntity *)uni_entities[i] retain];
662 //
663 //double found_d2 = scannerRange * scannerRange;
664 for (i = 0; i < wh_count ; i++)
665 {
666 WormholeEntity *wh = wormholes[i];
667 double d2 = HPdistance2(position, wh->position);
668 if (d2 < found_d2)
669 {
670 whole = wh;
671 found_d2 = d2;
672 }
673 [wh release];
674 }
675 }
676
677 [self enterWormhole:whole replacing:NO];
678}

◆ enterWitchspace

- (void) enterWitchspace

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

13518{
13519 [UNIVERSE addWitchspaceJumpEffectForShip:self];
13520 [shipAI message:@"ENTERED_WITCHSPACE"];
13521
13522 if (![[UNIVERSE sun] willGoNova])
13523 {
13524 // if the sun's not going nova, add a new ship like this one leaving.
13525 [UNIVERSE witchspaceShipWithPrimaryRole:[self primaryRole]];
13526 }
13527
13528 [UNIVERSE removeEntity:self];
13529}

◆ enterWormhole:

- (void) enterWormhole: (WormholeEntity *)  w_hole

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

13478 :(WormholeEntity *) w_hole
13479{
13480 [self enterWormhole:w_hole replacing:YES];
13481}

◆ enterWormhole:replacing:

- (void) enterWormhole: (WormholeEntity *)  w_hole
replacing: (BOOL)  replacing 

Definition at line 9589 of file ShipEntity.m.

13484 :(WormholeEntity *) w_hole replacing:(BOOL)replacing
13485{
13486 if (w_hole == nil) return;
13487 if ([self status] == STATUS_ENTERING_WITCHSPACE)
13488 {
13489 return; // has already entered a different wormhole
13490 }
13491 // Replacement ships now handled by system repopulator
13492
13493 // MKW 2011.02.27 - Moved here from ShipEntityAI so escorts reliably follow
13494 // mother in all wormhole cases, not just when the ship
13495 // creates the wormhole.
13496 [self addTarget:w_hole];
13497 [self setFoundTarget:w_hole];
13498 [shipAI reactToMessage:@"WITCHSPACE OKAY" context:@"performHyperSpaceExit"]; // must be a reaction, the ship is about to disappear
13499
13500 // CIM 2012.07.22 above only covers those cases where ship expected to leave
13501 if ([[self escortArray] count] > 1)
13502 {
13503 // so wormhole escorts anyway if it leaves unexpectedly.
13504 [self wormholeEscorts];
13505 }
13506
13507 if ([self scriptedMisjump])
13508 {
13509 [self setScriptedMisjump:NO];
13510 [w_hole setMisjumpWithRange:[self scriptedMisjumpRange]];
13511 [self setScriptedMisjumpRange:0.5];
13512 }
13513 [w_hole suckInShip: self]; // removes ship from universe
13514}
BOOL scriptedMisjump()
BOOL suckInShip:(ShipEntity *ship)
void setMisjumpWithRange:(GLfloat range)

◆ entityForShaderProperties

- (Entity *) entityForShaderProperties

Definition at line 14062 of file ShipEntity.m.

14589{
14590 return [self rootShipEntity];
14591}

◆ entityPersonality

- (GLfloat) entityPersonality

Definition at line 9589 of file ShipEntity.m.

9762{
9764}
#define ENTITY_PERSONALITY_MAX
Definition ShipEntity.h:110

◆ entityPersonalityInt

- (GLint) entityPersonalityInt

Definition at line 9589 of file ShipEntity.m.

9768{
9769 return entity_personality;
9770}

◆ equipmentCount

- (NSUInteger) equipmentCount

Definition at line 2092 of file ShipEntity.m.

3635{
3636 return [_equipment count];
3637}

◆ equipmentEnumerator

- (NSEnumerator *) equipmentEnumerator

Definition at line 2092 of file ShipEntity.m.

3629{
3630 return [_equipment objectEnumerator];
3631}

◆ equipmentItemProviding:

- (NSString *) equipmentItemProviding: (NSString *)  equipmentType

Definition at line 2092 of file ShipEntity.m.

3158 :(NSString *)equipmentType
3159{
3160 NSString *key = nil;
3161 foreach (key, _equipment) {
3162 if ([key isEqualToString:equipmentType])
3163 {
3164 // equipment always provides itself
3165 return [[key copy] autorelease];
3166 }
3167 else
3168 {
3170 if (et != nil && [et provides:equipmentType])
3171 {
3172 return [[key copy] autorelease];
3173 }
3174 }
3175 }
3176 return nil;
3177}

◆ equipmentListForScripting

- (NSArray *) equipmentListForScripting

Definition at line 2092 of file ShipEntity.m.

3351{
3352 NSArray *eqTypes = [OOEquipmentType allEquipmentTypes];
3353 NSMutableArray *quip = [NSMutableArray arrayWithCapacity:[eqTypes count]];
3354 OOEquipmentType *eqType = nil;
3355 BOOL isDamaged;
3356
3357 foreach (eqType, eqTypes)
3358 {
3359 // Equipment list, consistent with the rest of the API - Kaks
3360 if ([eqType canCarryMultiple])
3361 {
3362 NSString *damagedIdentifier = [[eqType identifier] stringByAppendingString:@"_DAMAGED"];
3363 NSUInteger i, count = 0;
3364 count += [self countEquipmentItem:[eqType identifier]];
3365 count += [self countEquipmentItem:damagedIdentifier];
3366 for (i=0;i<count;i++)
3367 {
3368 [quip addObject:eqType];
3369 }
3370 }
3371 else
3372 {
3373 isDamaged = [self hasEquipmentItem:[[eqType identifier] stringByAppendingString:@"_DAMAGED"]];
3374 if ([self hasEquipmentItem:[eqType identifier]] || isDamaged)
3375 {
3376 [quip addObject:eqType];
3377 }
3378 }
3379 }
3380
3381 // Passengers - not supported yet for NPCs, but it's here for genericity.
3382 if ([self passengerCapacity] > 0)
3383 {
3384 eqType = [OOEquipmentType equipmentTypeWithIdentifier:@"EQ_PASSENGER_BERTH"];
3385 //[quip addObject:[self eqDictionaryWithType:eqType isDamaged:NO]];
3386 [quip addObject:eqType];
3387 }
3388
3389 return [[quip copy] autorelease];
3390}
NSArray * allEquipmentTypes()
NSString * identifier()
NSUInteger passengerCapacity()

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ equipmentValidToAdd:inContext:

- (BOOL) equipmentValidToAdd: (NSString *)  equipmentKey
inContext: (NSString *)  context 

Definition at line 2092 of file ShipEntity.m.

3393 :(NSString *)equipmentKey inContext:(NSString *)context
3394{
3395 return [self equipmentValidToAdd:equipmentKey whileLoading:NO inContext:context];
3396}

◆ equipmentValidToAdd:whileLoading:inContext:

- (BOOL) equipmentValidToAdd: (NSString *)  equipmentKey
whileLoading: (BOOL)  loading
inContext: (NSString *)  context 

Definition at line 2092 of file ShipEntity.m.

3399 :(NSString *)equipmentKey whileLoading:(BOOL)loading inContext:(NSString *)context
3400{
3401 OOEquipmentType *eqType = nil;
3402 BOOL validationForDamagedEquipment = NO;
3403
3404 if ([equipmentKey hasSuffix:@"_DAMAGED"])
3405 {
3406 equipmentKey = [equipmentKey substringToIndex:[equipmentKey length] - [@"_DAMAGED" length]];
3407 }
3408
3409 eqType = [OOEquipmentType equipmentTypeWithIdentifier:equipmentKey];
3410 if (eqType == nil) return NO;
3411
3412 // need to know if we are trying to add a Repair version of the equipment. In some cases
3413 // (e.g. available cargo space required), it makes sense to deny installation of equipment
3414 // if the condition is not satisfied, but it doesn't make sense to deny repair when the
3415 // equipment is already installed. For now, we are checking only the cargo space condition,
3416 // but other conditions might need to be revised too. - Nikos, 20151115
3417 if ([self hasEquipmentItem:[eqType damagedIdentifier]])
3418 {
3419 validationForDamagedEquipment = YES;
3420 }
3421
3422 // not all conditions make sence checking while loading a game with already purchaged equipment.
3423 // while loading, we mainly need to catch changes when the installed oxps set has changed since saving.
3424 if ([eqType requiresEmptyPylon] && [self missileCount] >= [self missileCapacity] && !loading) return NO;
3425 if ([eqType requiresMountedPylon] && [self missileCount] == 0 && !loading) return NO;
3426 if ([self availableCargoSpace] < [eqType requiredCargoSpace] && !validationForDamagedEquipment && !loading) return NO;
3427 if ([eqType requiresEquipment] != nil && ![self hasAllEquipment:[eqType requiresEquipment] includeWeapons:YES whileLoading:loading]) return NO;
3428 if ([eqType requiresAnyEquipment] != nil && ![self hasEquipmentItem:[eqType requiresAnyEquipment] includeWeapons:YES whileLoading:loading]) return NO;
3429 if ([eqType incompatibleEquipment] != nil && [self hasEquipmentItem:[eqType incompatibleEquipment] includeWeapons:YES whileLoading:loading]) return NO;
3430 if ([eqType requiresCleanLegalRecord] && [self legalStatus] != 0 && !loading) return NO;
3431 if ([eqType requiresNonCleanLegalRecord] && [self legalStatus] == 0 && !loading) return NO;
3432 if ([eqType requiresFreePassengerBerth] && [self passengerCount] >= [self passengerCapacity]) return NO;
3433 if ([eqType requiresFullFuel] && [self fuel] < [self fuelCapacity] && !loading) return NO;
3434 if ([eqType requiresNonFullFuel] && [self fuel] >= [self fuelCapacity] && !loading) return NO;
3435
3436 if (!loading)
3437 {
3438 NSString *condition_script = [eqType conditionScript];
3439 if (condition_script != nil)
3440 {
3441 OOJSScript *condScript = [UNIVERSE getConditionScript:condition_script];
3442 if (condScript != nil) // should always be non-nil, but just in case
3443 {
3444 JSContext *JScontext = OOJSAcquireContext();
3445 BOOL OK;
3446 JSBool allow_addition = false;
3447 jsval result;
3448 jsval args[] = { OOJSValueFromNativeObject(JScontext, equipmentKey) , OOJSValueFromNativeObject(JScontext, self) , OOJSValueFromNativeObject(JScontext, context)};
3449
3450 OK = [condScript callMethod:OOJSID("allowAwardEquipment")
3451 inContext:JScontext
3452 withArguments:args count:sizeof args / sizeof *args
3453 result:&result];
3454
3455 if (OK) OK = JS_ValueToBoolean(JScontext, result, &allow_addition);
3456
3457 OOJSRelinquishContext(JScontext);
3458
3459 if (OK && !allow_addition)
3460 {
3461 /* if the script exists, the function exists, the function
3462 * returns a bool, and that bool is false, block
3463 * addition. Otherwise allow it as default */
3464 return NO;
3465 }
3466 }
3467 }
3468 }
3469
3470 if ([self isPlayer])
3471 {
3472 if (![eqType isAvailableToPlayer]) return NO;
3473 if (![eqType isAvailableToAll])
3474 {
3475 // find options that agree with this ship. Only player ships have these options.
3477 NSDictionary *shipyardInfo = [registry shipyardInfoForKey:[self shipDataKey]];
3478 NSMutableSet *options = [NSMutableSet setWithArray:[shipyardInfo oo_arrayForKey:KEY_OPTIONAL_EQUIPMENT]];
3479 [options addObjectsFromArray:[[shipyardInfo oo_dictionaryForKey:KEY_STANDARD_EQUIPMENT] oo_arrayForKey:KEY_EQUIPMENT_EXTRAS]];
3480 if (![options containsObject:equipmentKey]) return NO;
3481 }
3482 }
3483 else
3484 {
3485 if (![eqType isAvailableToNPCs]) return NO;
3486 }
3487
3488 return YES;
3489}
NSString * conditionScript()
BOOL callMethod:inContext:withArguments:count:result:(jsid methodID,[inContext] JSContext *context,[withArguments] jsval *argv,[count] intN argc,[result] jsval *outResult)
Definition OOJSScript.m:394
NSDictionary * shipyardInfoForKey:(NSString *key)
OOShipRegistry * sharedRegistry()
NSUInteger passengerCount()
NSUInteger missileCount()
OOCargoQuantity availableCargoSpace()
OOFuelQuantity fuelCapacity()
NSUInteger missileCapacity()

◆ escortArray

- (NSArray *) escortArray

Definition at line 6493 of file ShipEntity.m.

6988{
6989 if (_escortGroup == nil) return [NSArray array];
6990 return [[self escortEnumerator] allObjects];
6991}

◆ escortCheckMother

- (void) escortCheckMother
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1834{
1835 ShipEntity *mother = [self owner];
1836
1837 if ([mother acceptAsEscort:self])
1838 {
1839 [self setOwner:mother];
1840 [self setGroup:[mother escortGroup]];
1841 [shipAI message:@"ESCORTING"];
1842 }
1843 else
1844 {
1845 [self setOwner:self];
1846 if ([self group] == [mother escortGroup]) [self setGroup:nil];
1847 [shipAI message:@"NOT_ESCORTING"];
1848 }
1849}

◆ escortCount

- (uint8_t) escortCount

Definition at line 6493 of file ShipEntity.m.

6995{
6996 if (_escortGroup == nil) return 0;
6997 return [_escortGroup count] - 1;
6998}

◆ escortEnumerator

- (NSEnumerator *) escortEnumerator

Definition at line 6493 of file ShipEntity.m.

6981{
6982 if (_escortGroup == nil) return [[NSArray array] objectEnumerator];
6983 return [[_escortGroup mutationSafeEnumerator] ooExcludingObject:self];
6984}

◆ escortGroup

- (OOShipGroup *) escortGroup

Definition at line 6493 of file ShipEntity.m.

6930{
6931 if (_escortGroup == nil)
6932 {
6933 _escortGroup = [[OOShipGroup alloc] initWithName:@"escort group"];
6934 [_escortGroup setLeader:self];
6935 }
6936
6937 return _escortGroup;
6938}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ evasiveAction:

- (void) evasiveAction: (double)  delta_t

Definition at line 9589 of file ShipEntity.m.

10436 :(double) delta_t
10437{
10438 stick_roll = flightRoll; //desired roll and pitch
10440
10441 ShipEntity* target = [self primaryTarget];
10442 if (!target) // leave now!
10443 {
10444 [self noteLostTargetAndGoIdle]; // NOTE: was AI message: rather than reactToMessage:
10445 return;
10446 }
10447
10448 double agreement = dot_product(v_right,target->v_right);
10449 if (agreement > -0.3 && agreement < 0.3)
10450 {
10451 stick_roll = 0.0;
10452 }
10453 else
10454 {
10455 if (stick_roll >= 0.0) {
10457 } else {
10459 }
10460 }
10461 if (stick_pitch >= 0.0) {
10463 } else {
10465 }
10466
10467 [self applySticks:delta_t];
10468}

◆ exhaustEmissiveColor

- (OOColor *) exhaustEmissiveColor

Definition at line 9589 of file ShipEntity.m.

11717{
11718 return [[exhaust_emissive_color retain] autorelease];
11719}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ exhaustEnumerator

- (NSEnumerator *) exhaustEnumerator

Definition at line 14942 of file ShipEntity.m.

1350{
1351 return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isExhaust)];
1352}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ exitAIWithMessage:

- (void) exitAIWithMessage: (NSString *)  message
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1412 :(NSString *)message
1413{
1414 if ([message length] == 0) message = @"RESTARTED";
1415 [shipAI exitStateMachineWithMessage:message];
1416}

◆ explodeSelf

- (void) explodeSelf
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2638{
2639 [self getDestroyedBy:nil damageType:kOODamageTypeEnergy];
2640}

◆ extraCargo

- (NSUInteger) extraCargo

Definition at line 2092 of file ShipEntity.m.

3939{
3940 return extra_cargo;
3941}

◆ fightOrFleeHostiles

- (void) fightOrFleeHostiles
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1778{
1779 [self addDefenseTarget:[self foundTarget]];
1780
1781 if ([self hasEscorts])
1782 {
1783 Entity *leTarget = [self lastEscortTarget];
1784 if (leTarget != nil)
1785 {
1786 [self setFoundTarget:leTarget];
1787 [shipAI message:@"FLEEING"];
1788 return;
1789 }
1790
1791 [self setPrimaryAggressor:[self foundTarget]];
1792 [self addTarget:[self foundTarget]];
1793 [self deployEscorts];
1794 [shipAI message:@"DEPLOYING_ESCORTS"];
1795 [shipAI message:@"FLEEING"];
1796 return;
1797 }
1798
1799 // consider launching a missile
1800 if (missiles > 2) // keep a reserve
1801 {
1802 if (randf() < 0.50)
1803 {
1804 [self setPrimaryAggressor:[self foundTarget]];
1805 [self addTarget:[self foundTarget]];
1806 [self fireMissile];
1807 [shipAI message:@"FLEEING"];
1808 return;
1809 }
1810 }
1811
1812 // consider fighting
1813 if (energy > maxEnergy * 0.80)
1814 {
1815 [self setPrimaryAggressor:[self foundTarget]];
1816 //[self performAttack];
1817 [shipAI message:@"FIGHTING"];
1818 return;
1819 }
1820
1821 [shipAI message:@"FLEEING"];
1822}

◆ fightOrFleeMissile

- (void) fightOrFleeMissile
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1228{
1229 // find an incoming missile...
1230 //
1231 ShipEntity *missile = nil;
1232 unsigned i;
1233 ShipEntity *escort = nil;
1234 ShipEntity *target = nil;
1235
1236 [self checkScannerIgnoringUnpowered];
1237 for (i = 0; (i < n_scanned_ships)&&(missile == nil); i++)
1238 {
1239 ShipEntity *thing = scanned_ships[i];
1240 if (thing->scanClass == CLASS_MISSILE)
1241 {
1242 target = [thing primaryTarget];
1243
1244 if (target == self)
1245 {
1246 missile = thing;
1247 }
1248 else
1249 {
1250 foreach (escort, [self escortEnumerator])
1251 {
1252 if (target == escort)
1253 {
1254 missile = thing;
1255 }
1256 }
1257 }
1258 }
1259 }
1260
1261 if (missile == nil) return;
1262
1263 [self addTarget:missile];
1264 [self addDefenseTarget:missile];
1265
1266 // Notify own ship script that we are being attacked.
1267 ShipEntity *hunter = [missile owner];
1268 [self doScriptEvent:OOJSID("shipBeingAttacked") withArgument:hunter];
1269 [hunter doScriptEvent:OOJSID("shipAttackedOther") withArgument:self];
1270
1271 if ([self isPolice])
1272 {
1273 // Notify other police in group of attacker.
1274 // Note: prior to 1.73 this was done only if we had ECM.
1275 ShipEntity *police = nil;
1276
1277 foreach (police, [[self group] mutationSafeEnumerator])
1278 {
1279 [police setFoundTarget:hunter];
1280 [police setPrimaryAggressor:hunter];
1281 }
1282 }
1283
1284 // if I'm a copper and you're not, then mark the other as an offender!
1285 if ([self isPolice] && ![hunter isPolice]) [hunter markAsOffender:64 withReason:kOOLegalStatusReasonAttackedPolice];
1286
1287 if ([self hasECM])
1288 {
1289 // use the ECM and battle on
1290
1291 [self setPrimaryAggressor:hunter]; // lets get them now for that!
1292 [self setFoundTarget:hunter];
1293
1294 [self fireECM];
1295 return;
1296 }
1297
1298 // RUN AWAY !!
1299 desired_range = 10000;
1300 [self performFlee];
1301 [shipAI message:@"FLEEING"];
1302}
void setPrimaryAggressor:(Entity *targetEntity)
void markAsOffender:withReason:(int offence_value,[withReason] OOLegalStatusReason reason)

◆ findBoundingBoxRelativeTo:InVectors:_i:_j:

- (BoundingBox) findBoundingBoxRelativeTo: (Entity *)  other
InVectors: (Vector) 
_i: (Vector) 
_j: (Vector)  _k 
implementation

Definition at line 14062 of file ShipEntity.m.

14300 :(Entity *)other InVectors:(Vector) _i :(Vector) _j :(Vector) _k
14301{
14302 HPVector opv = other ? other->position : position;
14303 return [self findBoundingBoxRelativeToPosition:opv InVectors:_i :_j :_k];
14304}

◆ findBoundingBoxRelativeToPosition:InVectors:_i:_j:

- (BoundingBox) findBoundingBoxRelativeToPosition: (HPVector)  opv
InVectors: (Vector) 
_i: (Vector) 
_j: (Vector)  _k 
implementation

Definition at line 14942 of file ShipEntity.m.

1420 :(HPVector)opv InVectors:(Vector) _i :(Vector) _j :(Vector) _k
1421{
1422 // HPVect: check that this conversion doesn't lose needed precision
1423 return [[self mesh] findBoundingBoxRelativeToPosition:HPVectorToVector(opv)
1424 basis:_i :_j :_k
1425 selfPosition:HPVectorToVector(position)
1426 selfBasis:v_right :v_up :v_forward];
1427}

◆ findBoundingBoxRelativeToPosition:InVectors:i:j:

- (BoundingBox) findBoundingBoxRelativeToPosition: (HPVector)  opv
InVectors: (Vector) 
i: (Vector) 
j: (Vector)  k 

Referenced by abandonShip.

+ Here is the caller graph for this function:

◆ findNearestPlanet

- (OOPlanetEntity *) findNearestPlanet

Definition at line 7616 of file ShipEntity.m.

7633{
7634 /*
7635 Performance note: this method is called every frame by every ship, and
7636 has a significant profiler presence.
7637 -- Ahruman 2012-09-13
7638 */
7639 OOPlanetEntity *planet = nil, *bestPlanet = nil;
7640 float bestRange = INFINITY;
7641 HPVector myPosition = [self position];
7642
7643 // valgrind complains about this line here. Might be compiler/GNUstep bug?
7644 // should we go back to a traditional enumerator? - CIM
7645 // similar complaints about the other foreach() in this file
7646 foreach (planet, [UNIVERSE planets])
7647 {
7648 // Ignore miniature planets.
7649 if ([planet planetType] == STELLAR_TYPE_MINIATURE) continue;
7650
7651 float range = SurfaceDistanceSqaredV(myPosition, planet);
7652 if (range < bestRange)
7653 {
7654 bestPlanet = planet;
7655 bestRange = range;
7656 }
7657 }
7658
7659 return bestPlanet;
7660}
@ STELLAR_TYPE_MINIATURE

◆ findNearestPlanetExcludingMoons

- (OOPlanetEntity *) findNearestPlanetExcludingMoons

Definition at line 7616 of file ShipEntity.m.

7682{
7683 OOPlanetEntity *result = nil;
7684 OOPlanetEntity *planet = nil;
7685 NSArray *bodies = nil;
7686 NSArray *planets = nil;
7687 unsigned i;
7688
7689 bodies = [UNIVERSE planets];
7690 planets = [NSMutableArray arrayWithCapacity:[bodies count]];
7691
7692 for (i=0; i < [bodies count]; i++)
7693 {
7694 planet = [bodies objectAtIndex:i];
7695 if([planet planetType] == STELLAR_TYPE_NORMAL_PLANET)
7696 planets = [planets arrayByAddingObject:planet];
7697 }
7698
7699 if ([planets count] == 0) return nil;
7700
7701 planets = [planets sortedArrayUsingFunction:ComparePlanetsBySurfaceDistance context:self];
7702 result = [planets objectAtIndex:0];
7703
7704 return result;
7705}
@ STELLAR_TYPE_NORMAL_PLANET

◆ findNearestStellarBody

- (Entity< OOStellarBody > *) findNearestStellarBody

Definition at line 7616 of file ShipEntity.m.

7664{
7665 Entity<OOStellarBody> *match = [self findNearestPlanet];
7666 OOSunEntity *sun = [UNIVERSE sun];
7667
7668 if (sun != nil)
7669 {
7670 if (match == nil ||
7671 SurfaceDistanceSqared(self, sun) < SurfaceDistanceSqared(self, match))
7672 {
7673 match = sun;
7674 }
7675 }
7676
7677 return match;
7678}
static float SurfaceDistanceSqared(Entity *reference, Entity< OOStellarBody > *stellar)

◆ findNewDefenseTarget

- (void) findNewDefenseTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1539{
1540 [self checkScanner];
1541 unsigned i;
1542 for (i = 0; i < n_scanned_ships ; i++)
1543 {
1544 ShipEntity *ship = scanned_ships[i];
1545 if (![ship isCloaked] && (([ship primaryTarget] == self && [ship hasHostileTarget]) || [ship isMine] || ([ship isThargoid] != [self isThargoid])))
1546 {
1547 if (![self isDefenseTarget:ship])
1548 {
1549 [self addDefenseTarget:ship];
1550 return;
1551 }
1552 }
1553 }
1554}

◆ findSubentityBoundingBox

- (BoundingBox) findSubentityBoundingBox

Definition at line 2092 of file ShipEntity.m.

2228{
2229 return [[self mesh] findSubentityBoundingBoxWithPosition:HPVectorToVector(position) rotMatrix:rotMatrix];
2230}

◆ fireAftWeapon:

- (BOOL) fireAftWeapon: (double)  range

Definition at line 9589 of file ShipEntity.m.

11595 :(double)range
11596{
11597 // set the values from aft_weapon_type.
11599 [self setWeaponDataFromType:aft_weapon_type];
11600
11601 return [self fireWeapon:aft_weapon_type direction:WEAPON_FACING_AFT range:range];
11602}

◆ fireDirectLaserDefensiveShot

- (BOOL) fireDirectLaserDefensiveShot

Definition at line 9589 of file ShipEntity.m.

11821{
11822 NSEnumerator *targetEnum = [self defenseTargetEnumerator];
11823 Entity *target = nil;
11824 while ((target = [[targetEnum nextObject] weakRefUnderlyingObject]))
11825 {
11826 // can't fire defensively at cloaked ships
11827 if ([target scanClass] == CLASS_NO_DRAW || [(ShipEntity *)target isCloaked] || [target energy] <= 0.0)
11828 {
11829 [self removeDefenseTarget:target];
11830 }
11831 else
11832 {
11833 double range = [self rangeToSecondaryTarget:target];
11834 if (range < weaponRange)
11835 {
11836 return [self fireDirectLaserShotAt:target];
11837 }
11838 else if (range > scannerRange)
11839 {
11840 [self removeDefenseTarget:target];
11841 }
11842 }
11843 }
11844 return NO;
11845}

◆ fireDirectLaserShot:

- (BOOL) fireDirectLaserShot: (double)  range

Definition at line 9589 of file ShipEntity.m.

11810 :(double)range
11811{
11812 Entity *my_target = [self primaryTarget];
11813 if (my_target == nil) return [self fireDirectLaserDefensiveShot];
11814 if (range > randf() * weaponRange * (accuracy+5.5)) return [self fireDirectLaserDefensiveShot];
11815 if (range > weaponRange) return [self fireDirectLaserDefensiveShot];
11816 return [self fireDirectLaserShotAt:my_target];
11817}
BOOL fireDirectLaserDefensiveShot()

◆ fireDirectLaserShotAt:

- (BOOL) fireDirectLaserShotAt: (Entity *)  my_target

Definition at line 9589 of file ShipEntity.m.

11848 :(Entity *)my_target
11849{
11850 GLfloat hit_at_range;
11851 double range_limit2 = weaponRange*weaponRange;
11852 Vector r_pos;
11853
11854 r_pos = vector_normal_or_zbasis([self vectorTo:my_target]);
11855
11856 Quaternion q_laser = quaternion_rotation_between(r_pos, kBasisZVector);
11857
11858 GLfloat acc_factor = (10.0 - accuracy) * 0.001;
11859
11860 q_laser.x += acc_factor * (randf() - 0.5); // randomise aim a little (+/- 0.005 at accuracy 0, never miss at accuracy 10)
11861 q_laser.y += acc_factor * (randf() - 0.5);
11862 q_laser.z += acc_factor * (randf() - 0.5);
11863 quaternion_normalize(&q_laser);
11864
11865 Quaternion q_save = orientation; // save rotation
11866 orientation = q_laser; // face in direction of laser
11867 // weapon offset for thargoid lasers is always zero
11868 ShipEntity *victim = [UNIVERSE firstShipHitByLaserFromShip:self inDirection:WEAPON_FACING_FORWARD offset:kZeroVector gettingRangeFound:&hit_at_range];
11869 [self setShipHitByLaser:victim];
11870 orientation = q_save; // restore rotation
11871
11872 Vector vel = vector_multiply_scalar(v_forward, flightSpeed);
11873
11874 // do special effects laser line
11875 OOLaserShotEntity *shot = [OOLaserShotEntity laserFromShip:self direction:WEAPON_FACING_FORWARD offset:kZeroVector];
11876 [shot setColor:laser_color];
11877 [shot setScanClass: CLASS_NO_DRAW];
11878 [shot setPosition: position];
11879 [shot setOrientation: q_laser];
11880 [shot setVelocity: vel];
11881
11882 if (victim != nil)
11883 {
11884 ShipEntity *subent = [victim subEntityTakingDamage];
11885 if (subent != nil && [victim isFrangible])
11886 {
11887 // do 1% bleed-through damage...
11888 [victim takeEnergyDamage: 0.01 * weapon_damage from:self becauseOf:self weaponIdentifier:[[self weaponTypeForFacing:WEAPON_FACING_FORWARD strict:YES] identifier]];
11889 victim = subent;
11890 }
11891
11892 if (hit_at_range * hit_at_range < range_limit2)
11893 {
11894 [victim takeEnergyDamage:weapon_damage from:self becauseOf:self weaponIdentifier:[[self weaponTypeForFacing:WEAPON_FACING_FORWARD strict:YES] identifier]]; // a very palpable hit
11895
11896 [shot setRange:hit_at_range];
11897 Vector vd = vector_forward_from_quaternion([shot orientation]);
11898 HPVector flash_pos = HPvector_add([shot position], vectorToHPVector(vector_multiply_scalar(vd, hit_at_range)));
11899 [UNIVERSE addLaserHitEffectsAt:flash_pos against:victim damage:weapon_damage color:laser_color];
11900 }
11901 }
11902
11903 [UNIVERSE addEntity:shot];
11904
11905 [self resetShotTime];
11906
11907 return YES;
11908}
void setRange:(GLfloat range)
void setColor:(OOColor *color)
instancetype laserFromShip:direction:offset:(ShipEntity *ship,[direction] OOWeaponFacing direction,[offset] Vector offset)
ShipEntity * subEntityTakingDamage()

◆ fireECM

- (BOOL) fireECM

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12348{
12349 if (![self hasECM]) return NO;
12350
12351 OOECMBlastEntity *ecmDevice = [[OOECMBlastEntity alloc] initFromShip:self];
12352 [UNIVERSE addEntity:ecmDevice];
12353 [ecmDevice release];
12354 return YES;
12355}

Referenced by ShipFireECM().

+ Here is the caller graph for this function:

◆ fireLaserShotInDirection:weaponIdentifier:

- (BOOL) fireLaserShotInDirection: (OOWeaponFacing direction
weaponIdentifier: (NSString *)  weaponIdentifier 

Definition at line 9589 of file ShipEntity.m.

11937 :(OOWeaponFacing)direction weaponIdentifier:(NSString *)weaponIdentifier
11938{
11939 double range_limit2 = weaponRange * weaponRange;
11940 GLfloat hit_at_range;
11941 NSUInteger i, barrels;
11942 Vector vel = vector_multiply_scalar(v_forward, flightSpeed);
11943 NSArray *laserPortOffsets = [self laserPortOffset:direction];
11944 OOLaserShotEntity *shot = nil;
11945
11946 barrels = [laserPortOffsets count];
11947 NSMutableArray *shotEntities = [NSMutableArray arrayWithCapacity:barrels];
11948
11949
11950 GLfloat effective_damage = weapon_damage;
11951 if (barrels > 1 && !_multiplyWeapons)
11952 {
11953 // then divide the shot power between the shots
11954 effective_damage /= (GLfloat)barrels;
11955 }
11956
11957 for (i=0;i<barrels;i++)
11958 {
11959 Vector laserPortOffset = [laserPortOffsets oo_vectorAtIndex:i];
11960
11961 last_shot_time = [UNIVERSE getTime];
11962
11963 ShipEntity *victim = [UNIVERSE firstShipHitByLaserFromShip:self inDirection:direction offset:laserPortOffset gettingRangeFound:&hit_at_range];
11964 [self setShipHitByLaser:victim];
11965
11966 shot = [OOLaserShotEntity laserFromShip:self direction:direction offset:laserPortOffset];
11967 if ([self isPlayer])
11968 {
11969 [shotEntities addObject:shot];
11970 }
11971
11972 [shot setColor:laser_color];
11973 [shot setScanClass: CLASS_NO_DRAW];
11974 [shot setVelocity: vel];
11975
11976 if (victim != nil)
11977 {
11978 [self adjustMissedShots:-1];
11979 if ([self isPlayer])
11980 {
11981 [PLAYER addRoleForAggression:victim];
11982 }
11983
11984 /* CRASH in [victim->sub_entities containsObject:subent] here (1.69, OS X/x86).
11985 Analysis: Crash is in _freedHandler called from CFEqual, indicating either a dead
11986 object in victim->sub_entities or dead victim->subentity_taking_damage. I suspect
11987 the latter. Probable solution: dying subentities must cause parent to clean up
11988 properly. This was probably obscured by the entity recycling scheme in the past.
11989 Fix: made subentity_taking_damage a weak reference accessed via a method.
11990 -- Ahruman 20070706, 20080304
11991 */
11992 ShipEntity *subent = [victim subEntityTakingDamage];
11993 if (subent != nil && [victim isFrangible])
11994 {
11995 // do 1% bleed-through damage...
11996 [victim takeEnergyDamage: 0.01 * effective_damage from:self becauseOf:self weaponIdentifier:weaponIdentifier];
11997 victim = subent;
11998 }
11999
12000 if (hit_at_range * hit_at_range < range_limit2)
12001 {
12002 [victim takeEnergyDamage:effective_damage from:self becauseOf:self weaponIdentifier:weaponIdentifier]; // a very palpable hit
12003
12004 [shot setRange:hit_at_range];
12005 Vector vd = vector_forward_from_quaternion([shot orientation]);
12006 HPVector flash_pos = HPvector_add([shot position], vectorToHPVector(vector_multiply_scalar(vd, hit_at_range)));
12007 [UNIVERSE addLaserHitEffectsAt:flash_pos against:victim damage:effective_damage color:laser_color];
12008 }
12009 }
12010 else
12011 {
12012 [self adjustMissedShots:+1];
12013
12014 // shot missed
12015 if (![self isCloaked])
12016 {
12017 victim = [self primaryTarget];
12018 if ([victim isShip]) // it might not be - fixes crash bug
12019 {
12020
12021 /* player currently gets a bit of an advantage here if
12022 * they ambush without having their target actually
12023 * targeted. Though in those circumstances they
12024 * shouldn't be missing their first shot anyway. */
12025 if (dot_product(vector_forward_from_quaternion([shot orientation]),vector_normal([self vectorTo:victim])) > 0.995)
12026 {
12027 /* plausibly aimed at target. Allows reaction
12028 * before attacker actually hits. But we need to
12029 * be able to distinguish in AI from ATTACKED so
12030 * that ships in combat aren't bothered by
12031 * amateurs. So should only respond to
12032 * ATTACKER_MISSED if not already fighting */
12033 if ([self isPlayer])
12034 {
12035 [PLAYER addRoleForAggression:victim];
12036 }
12037 [victim setPrimaryAggressor:self];
12038 [victim setFoundTarget:self];
12039 [victim reactToAIMessage:@"ATTACKER_MISSED" context:@"attacker narrowly misses"];
12040 [victim doScriptEvent:OOJSID("shipBeingAttackedUnsuccessfully") withArgument:self];
12041 }
12042 }
12043 }
12044 }
12045
12046 [UNIVERSE addEntity:shot];
12047
12048 }
12049
12050 if ([self isPlayer])
12051 {
12052 [(PlayerEntity *)self setLastShot:shotEntities];
12053 }
12054
12055 [self resetShotTime];
12056
12057 return YES;
12058}
OOWeaponFacing
Definition OOTypes.h:228
OOTimeAbsolute last_shot_time
Definition ShipEntity.h:359
BOOL _multiplyWeapons
Definition ShipEntity.h:391

◆ fireMainWeapon:

- (BOOL) fireMainWeapon: (double)  range

Definition at line 9589 of file ShipEntity.m.

11549 :(double)range
11550{
11551 // set the values from forward_weapon_type.
11552 // OXPs can override the default front laser energy damage.
11554 [self setWeaponDataFromType:forward_weapon_type];
11555
11556// weapon damage override no longer effective
11557// weapon_damage = weapon_damage_override;
11558
11559 BOOL result = [self fireWeapon:forward_weapon_type direction:WEAPON_FACING_FORWARD range:range];
11561 {
11562 // need to check subentities to avoid AI oddities
11563 // will already have fired them by now, though
11564 NSEnumerator *subEnum = [self shipSubEntityEnumerator];
11565 ShipEntity *se = nil;
11566 OOWeaponType weapon_type = nil;
11567 BOOL hasTurrets = NO;
11568 while (isWeaponNone(weapon_type) && (se = [subEnum nextObject]))
11569 {
11570 weapon_type = se->forward_weapon_type;
11572 if (se->behaviour == BEHAVIOUR_TRACK_AS_TURRET)
11573 {
11574 hasTurrets = YES;
11575 }
11576 }
11577 if (isWeaponNone(weapon_type) && hasTurrets)
11578 { /* no forward weapon but has turrets, so set up range calculations accordingly
11579 note: this was hard-coded to 10000.0, although turrets have a notably
11580 shorter range. We are using a multiplier of 1.667 in order to not change
11581 something that already works, but probably it would be best to use
11582 TURRET_SHOT_RANGE * COMBAT_WEAPON_RANGE_FACTOR here
11583 */
11585 }
11586 else
11587 {
11588 [self setWeaponDataFromType:weapon_type];
11589 }
11590 }
11591 return result;
11592}
#define TURRET_SHOT_RANGE
Definition ShipEntity.h:82

◆ fireMissile

- (ShipEntity *) fireMissile

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12166{
12167 return [self fireMissileWithIdentifier:nil andTarget:[self primaryTarget]];
12168}

Referenced by ShipFireMissile().

+ Here is the caller graph for this function:

◆ fireMissileWithIdentifier:andTarget:

- (ShipEntity *) fireMissileWithIdentifier: (NSString *)  identifier
andTarget: (Entity *)  target 

Definition at line 9589 of file ShipEntity.m.

12171 :(NSString *) identifier andTarget:(Entity *) target
12172{
12173 // both players and NPCs!
12174 //
12175 ShipEntity *missile = nil;
12176 ShipEntity *target_ship = nil;
12177
12178 Vector vel;
12179 Vector start, v_eject;
12180
12181 if ([UNIVERSE getTime] < missile_launch_time) return nil;
12182
12183 start = [self missileLaunchPosition];
12184
12185 double throw_speed = 250.0f;
12186
12187 if ((missiles <= 0)||(target == nil)||([target scanClass] == CLASS_NO_DRAW)) // no missile lock!
12188 return nil;
12189
12190 if ([target isShip])
12191 {
12192 target_ship = (ShipEntity*)target;
12193 if ([target_ship isCloaked])
12194 {
12195 return nil;
12196 }
12197 // missile fire requires being in scanner range
12198 if (HPmagnitude2(HPvector_subtract([target_ship position], position)) > scannerRange * scannerRange)
12199 {
12200 return nil;
12201 }
12202 if (![self hasMilitaryScannerFilter] && [target_ship isJammingScanning])
12203 {
12204 return nil;
12205 }
12206 }
12207
12208 unsigned i;
12209 if (identifier == nil)
12210 {
12211 // use a random missile from the list
12212 i = floor(randf()*(double)missiles);
12213 identifier = [missile_list[i] identifier];
12214 missile = [UNIVERSE newShipWithRole:identifier];
12215 if (EXPECT_NOT(missile == nil)) // invalid missile role.
12216 {
12217 // remove that invalid missile role from the missiles list.
12218 while ( ++i < missiles ) missile_list[i - 1] = missile_list[i];
12219 missiles--;
12220 }
12221 }
12222 else
12223 missile = [UNIVERSE newShipWithRole:identifier];
12224
12225 if (EXPECT_NOT(missile == nil)) return nil;
12226
12227 // By definition, the player will always have the specified missile.
12228 // What if the NPC didn't actually have the specified missile to begin with?
12229 if (!isPlayer && ![self removeExternalStore:[OOEquipmentType equipmentTypeWithIdentifier:identifier]])
12230 {
12231 [missile release];
12232 return nil;
12233 }
12234
12235 double mcr = missile->collision_radius;
12236 v_eject = vector_normal(start);
12237 vel = kZeroVector; // starting velocity
12238
12239 // check if start is within bounding box...
12240 while ( (start.x > boundingBox.min.x - mcr)&&(start.x < boundingBox.max.x + mcr)&&
12241 (start.y > boundingBox.min.y - mcr)&&(start.y < boundingBox.max.y + mcr)&&
12242 (start.z > boundingBox.min.z - mcr)&&(start.z < boundingBox.max.z + mcr) )
12243 {
12244 start = vector_add(start, vector_multiply_scalar(v_eject, mcr));
12245 }
12246
12247 vel = vector_add(vel, vector_multiply_scalar(v_forward, flightSpeed + throw_speed));
12248
12249 Quaternion q1 = [self normalOrientation];
12250 HPVector origin = HPvector_add(position, vectorToHPVector(quaternion_rotate_vector(q1, start)));
12251
12252 if (isPlayer) [missile setScanClass: CLASS_MISSILE];
12253
12254// special cases
12255
12256 //We don't want real missiles in a group. Missiles could become escorts when the group is also used as escortGroup.
12257 if ([missile scanClass] == CLASS_THARGOID)
12258 {
12259 if([self group] == nil) [self setGroup:[OOShipGroup groupWithName:@"thargoid group"]];
12260
12261 ShipEntity *thisGroupLeader = [_group leader];
12262
12263 if ([thisGroupLeader escortGroup] != _group) // avoid adding tharons to escort groups
12264 {
12265 [missile setGroup:[self group]];
12266 }
12267 }
12268
12269 // is this a submunition?
12270 if (![self isMissileFlagSet]) [missile setOwner:self];
12271 else [missile setOwner:[self owner]];
12272
12273// end special cases
12274
12275 [missile setPosition:origin];
12276 [missile addTarget:target];
12277 [missile setOrientation:q1];
12278 [missile setIsMissileFlag:YES];
12279 [missile setVelocity:vel];
12280 [missile setSpeed:150.0f];
12281 [missile setDistanceTravelled:0.0f];
12282 [missile resetShotTime];
12283 missile_launch_time = [UNIVERSE getTime] + missile_load_time; // set minimum launchtime for the next missile.
12284
12285 [UNIVERSE addEntity:missile]; // STATUS_IN_FLIGHT, AI state GLOBAL
12286 [missile release]; //release
12287
12288 // missile lives on after UNIVERSE addEntity
12289 if ([missile isMissile] && [target isShip])
12290 {
12291 [self doScriptEvent:OOJSID("shipFiredMissile") withArgument:missile andArgument:target_ship];
12292 [target_ship setPrimaryAggressor:self];
12293 [target_ship doScriptEvent:OOJSID("shipAttackedWithMissile") withArgument:missile andArgument:self];
12294 [target_ship reactToAIMessage:@"INCOMING_MISSILE" context:@"someone's shooting at me!"];
12296 {
12297 // parity between player &NPCs, only deactivate cloak for missiles
12298 [self deactivateCloakingDevice];
12299 }
12300 }
12301 else
12302 {
12303 [self doScriptEvent:OOJSID("shipReleasedEquipment") withArgument:missile];
12304 }
12305
12306 return missile;
12307}
void setDistanceTravelled:(GLfloat value)
Definition Entity.m:782
instancetype groupWithName:(NSString *name)
BOOL isJammingScanning()
void setSpeed:(double amount)
OOTimeDelta missile_load_time
Definition ShipEntity.h:322
BOOL hasMilitaryScannerFilter()
OOTimeAbsolute missile_launch_time
Definition ShipEntity.h:323
BOOL isMissileFlagSet()
unsigned cloakPassive
Definition ShipEntity.h:266
void resetShotTime()
void setIsMissileFlag:(BOOL newValue)
voidpf uLong int origin
Definition ioapi.h:140

Referenced by ShipFireMissile().

+ Here is the caller graph for this function:

◆ firePortWeapon:

- (BOOL) firePortWeapon: (double)  range

Definition at line 9589 of file ShipEntity.m.

11605 :(double)range
11606{
11607 // set the values from port_weapon_type.
11609 [self setWeaponDataFromType:port_weapon_type];
11610
11611 return [self fireWeapon:port_weapon_type direction:WEAPON_FACING_PORT range:range];
11612}

◆ fireStarboardWeapon:

- (BOOL) fireStarboardWeapon: (double)  range

Definition at line 9589 of file ShipEntity.m.

11615 :(double)range
11616{
11617 // set the values from starboard_weapon_type.
11619 [self setWeaponDataFromType:starboard_weapon_type];
11620
11621 return [self fireWeapon:starboard_weapon_type direction:WEAPON_FACING_STARBOARD range:range];
11622}

◆ fireSubentityLaserShot:

- (BOOL) fireSubentityLaserShot: (double)  range

Definition at line 9589 of file ShipEntity.m.

11722 :(double)range
11723{
11724 [self setShipHitByLaser:nil];
11725
11726 if (isWeaponNone(forward_weapon_type)) return NO;
11727 [self setWeaponDataFromType:forward_weapon_type];
11728
11729 ShipEntity *parent = [self owner];
11730 NSAssert([parent isShipWithSubEntityShip:self], @"-fireSubentityLaserShot: called on ship which is not a subentity.");
11731
11732 // subentity lasers still draw power from the main entity
11733 if ([parent energy] <= weapon_energy_use) return NO;
11734 if ([self shotTime] < weapon_recharge_rate) return NO;
11736 if (range > weaponRange) return NO;
11737
11739 [parent setEnergy:([parent energy] - weapon_energy_use)];
11740
11741 GLfloat hitAtRange = weaponRange;
11743 ShipEntity *victim = [UNIVERSE firstShipHitByLaserFromShip:self inDirection:direction offset:kZeroVector gettingRangeFound:&hitAtRange];
11744 [self setShipHitByLaser:victim];
11745
11746 OOLaserShotEntity *shot = [OOLaserShotEntity laserFromShip:self direction:direction offset:kZeroVector];
11747 [shot setColor:laser_color];
11748 [shot setScanClass:CLASS_NO_DRAW];
11749
11750 if (victim != nil)
11751 {
11752 [self adjustMissedShots:-1];
11753
11754 if ([self isPlayer])
11755 {
11756 [PLAYER addRoleForAggression:victim];
11757 }
11758
11759 ShipEntity *subent = [victim subEntityTakingDamage];
11760 if (subent != nil && [victim isFrangible])
11761 {
11762 // do 1% bleed-through damage...
11763 [victim takeEnergyDamage:0.01 * weapon_damage from:self becauseOf:parent weaponIdentifier:[[self weaponTypeForFacing:WEAPON_FACING_FORWARD strict:YES] identifier]];
11764 victim = subent;
11765 }
11766
11767 if (hitAtRange < weaponRange)
11768 {
11769 [victim takeEnergyDamage:weapon_damage from:self becauseOf:parent weaponIdentifier:[[self weaponTypeForFacing:WEAPON_FACING_FORWARD strict:YES] identifier]]; // a very palpable hit
11770
11771 [shot setRange:hitAtRange];
11772 Vector vd = vector_forward_from_quaternion([shot orientation]);
11773 HPVector flash_pos = HPvector_add([shot position], vectorToHPVector(vector_multiply_scalar(vd, hitAtRange)));
11774 [UNIVERSE addLaserHitEffectsAt:flash_pos against:victim damage:weapon_damage color:laser_color];
11775 }
11776 }
11777 else
11778 {
11779 [self adjustMissedShots:+1];
11780
11781 // see ATTACKER_MISSED section of main entity laser routine
11782 if (![parent isCloaked])
11783 {
11784 victim = [parent primaryTarget];
11785
11786 Vector shotDirection = vector_forward_from_quaternion([shot orientation]);
11787 Vector victimDirection = vector_normal(HPVectorToVector(HPvector_subtract([victim position], [parent position])));
11788 if (dot_product(shotDirection, victimDirection) > 0.995) // Within 84.26 degrees
11789 {
11790 if ([self isPlayer])
11791 {
11792 [PLAYER addRoleForAggression:victim];
11793 }
11794 [victim setPrimaryAggressor:parent];
11795 [victim setFoundTarget:parent];
11796 [victim reactToAIMessage:@"ATTACKER_MISSED" context:@"attacker narrowly misses"];
11797 [victim doScriptEvent:OOJSID("shipBeingAttackedUnsuccessfully") withArgument:parent];
11798
11799 }
11800 }
11801 }
11802
11803 [UNIVERSE addEntity:shot];
11804 [self resetShotTime];
11805
11806 return YES;
11807}
#define NPC_MAX_WEAPON_TEMP
Definition ShipEntity.h:115
#define WEAPON_COOLING_CUTOUT
Definition ShipEntity.h:116
GLfloat weapon_energy_use
Definition ShipEntity.h:314
GLfloat weapon_shot_temperature
Definition ShipEntity.h:314
float weapon_recharge_rate
Definition ShipEntity.h:356

◆ fireTurretCannon:

- (BOOL) fireTurretCannon: (double)  range

Definition at line 9589 of file ShipEntity.m.

11637 :(double) range
11638{
11639 if ([self shotTime] < weapon_recharge_rate)
11640 return NO;
11641 if (range > weaponRange * 1.01) // 1% more than max range - open up just slightly early
11642 return NO;
11643 ShipEntity *root = [self rootShipEntity];
11644 if ([root isPlayer] && ![PLAYER weaponsOnline])
11645 return NO;
11646
11647 if ([root isCloaked] && [root cloakPassive])
11648 {
11649 // can't fire turrets while cloaked
11650 return NO;
11651 }
11652
11653 Vector vel;
11654 HPVector origin = [self position];
11655
11656 Entity *last = nil;
11657 Entity *father = [self parentEntity];
11658 OOMatrix r_mat;
11659
11661 // adjust velocity and position vectors to absolute coordinates
11662 while ((father)&&(father != last) && (father != NO_TARGET))
11663 {
11664 r_mat = [father drawRotationMatrix];
11665 origin = HPvector_add(OOHPVectorMultiplyMatrix(origin, r_mat), [father position]);
11666 vel = OOVectorMultiplyMatrix(vel, r_mat);
11667 last = father;
11668 if (![last isSubEntity]) break;
11669 father = [father owner];
11670 }
11671
11672 origin = HPvector_add(origin, vectorToHPVector(vector_multiply_scalar(vel, collision_radius + 0.5))); // Start just outside collision sphere
11673 vel = vector_multiply_scalar(vel, TURRET_SHOT_SPEED); // Shot velocity
11674
11675 OOPlasmaShotEntity *shot = [[OOPlasmaShotEntity alloc] initWithPosition:origin
11676 velocity:vel
11677 energy:weapon_damage
11678 duration:weaponRange/TURRET_SHOT_SPEED
11679 color:laser_color];
11680
11681 [shot autorelease];
11682 [UNIVERSE addEntity:shot];
11683 [shot setOwner:[self rootShipEntity]]; // has to be done AFTER adding shot to the UNIVERSE
11684
11685 [self resetShotTime];
11686 return YES;
11687}
HPVector OOHPVectorMultiplyMatrix(HPVector v, OOMatrix m)
Definition OOMatrix.m:145

◆ fireWeapon:direction:range:

- (BOOL) fireWeapon: (OOWeaponType weapon_type
direction: (OOWeaponFacing direction
range: (double)  range 
implementation

Definition at line 9589 of file ShipEntity.m.

11444 :(OOWeaponType)weapon_type direction:(OOWeaponFacing)direction range:(double)range
11445{
11446 weapon_temp = 0.0;
11447 switch (direction)
11448 {
11451 break;
11452
11453 case WEAPON_FACING_AFT:
11455 break;
11456
11457 case WEAPON_FACING_PORT:
11459 break;
11460
11463 break;
11464
11465 case WEAPON_FACING_NONE:
11466 break;
11467 }
11469
11470 NSUInteger multiplier = 1;
11471 if (_multiplyWeapons)
11472 {
11473 // multiple fitted
11474 multiplier = [[self laserPortOffset:direction] count];
11475 }
11476
11477 if (energy <= weapon_energy_use * multiplier) return NO;
11478 if ([self shotTime] < weapon_recharge_rate) return NO;
11479 if (![weapon_type isTurretLaser])
11480 { // thargoid laser may just pick secondary target in this case
11481 if (range > randf() * weaponRange * (accuracy+7.5)) return NO;
11482 if (range > weaponRange) return NO;
11483 }
11484 if (![self onTarget:direction withWeapon:weapon_type]) return NO;
11485
11486 BOOL fired = NO;
11487 if (!isWeaponNone(weapon_type))
11488 {
11489 if ([weapon_type isTurretLaser])
11490 {
11491 [self fireDirectLaserShot:range];
11492 fired = YES;
11493 }
11494 else
11495 {
11496 [self fireLaserShotInDirection:direction weaponIdentifier:[weapon_type identifier]];
11497 fired = YES;
11498 }
11499 }
11500
11501 if (fired)
11502 {
11503 energy -= weapon_energy_use * multiplier;
11504 switch (direction)
11505 {
11508 break;
11509
11510 case WEAPON_FACING_AFT:
11512 break;
11513
11514 case WEAPON_FACING_PORT:
11516 break;
11517
11520 break;
11521
11522 case WEAPON_FACING_NONE:
11523 break;
11524 }
11525 }
11526
11527 if (direction == WEAPON_FACING_FORWARD)
11528 {
11529 //can we fire lasers from our subentities?
11530 ShipEntity *se = nil;
11531 foreach (se, [self shipSubEntityEnumerator])
11532 {
11533 if ([se fireSubentityLaserShot:range])
11534 {
11535 fired = YES;
11536 }
11537 }
11538 }
11539
11540 if (fired && cloaking_device_active && cloakPassive)
11541 {
11542 [self deactivateCloakingDevice];
11543 }
11544
11545 return fired;
11546}
@ WEAPON_FACING_NONE
Definition OOTypes.h:234
OOEquipmentType * OOWeaponType
Definition ShipEntity.h:168

◆ flasherEnumerator

- (NSEnumerator *) flasherEnumerator

Definition at line 14942 of file ShipEntity.m.

1344{
1345 return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isFlasher)];
1346}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ flightPitch

- (GLfloat) flightPitch

◆ flightRoll

- (GLfloat) flightRoll

◆ flightSpeed

- (GLfloat) flightSpeed

◆ flightYaw

- (GLfloat) flightYaw

◆ forceAegisCheck

- (void) forceAegisCheck

Definition at line 7616 of file ShipEntity.m.

7871{
7872 _nextAegisCheck = -1.0f;
7873}
double _nextAegisCheck
Definition ShipEntity.h:490

◆ forwardVector

- (Vector) forwardVector

Definition at line 14942 of file ShipEntity.m.

1272{
1273 return v_forward;
1274}

◆ forwardWeaponOffset

- (NSArray *) forwardWeaponOffset

◆ foundTarget

- (Entity *) foundTarget

Definition at line 9589 of file ShipEntity.m.

9913{
9914 Entity *result = [_foundTarget weakRefUnderlyingObject];
9915 if (result == nil || ![self isValidTarget:result])
9916 {
9918 return nil;
9919 }
9920 return result;
9921}
OOWeakReference * _foundTarget
Definition ShipEntity.h:440

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ frustration

- (double) frustration

◆ frustumRadius

- (GLfloat) frustumRadius

Reimplemented from Entity.

Definition at line 14942 of file ShipEntity.m.

891{
892 OOScalar exhaust_length = 0;
893 NSEnumerator *exEnum = nil;
894 OOExhaustPlumeEntity *exEnt = nil;
895 for (exEnum = [self exhaustEnumerator]; (exEnt = [exEnum nextObject]); )
896 {
897 if ([exEnt findCollisionRadius] > exhaust_length)
898 {
899 exhaust_length = [exEnt findCollisionRadius];
900 }
901 }
902 return _profileRadius + exhaust_length;
903}
GLfloat OOScalar
Definition OOMaths.h:64
NSEnumerator * exhaustEnumerator()

◆ fuel

- (OOFuelQuantity) fuel

◆ fuelCapacity

- (OOFuelQuantity) fuelCapacity

Definition at line 7616 of file ShipEntity.m.

8116{
8117 // FIXME: shipdata.plist can allow greater fuel quantities (without extending hyperspace range). Need some consistency here.
8118 return PLAYER_MAX_FUEL;
8119}
#define PLAYER_MAX_FUEL

◆ fuelChargeRate

- (GLfloat) fuelChargeRate

Definition at line 7616 of file ShipEntity.m.

8123{
8124 GLfloat rate = 1.0; // Standard (& strict play) charge rate.
8125
8126#if MASS_DEPENDENT_FUEL_PRICES
8127
8128 if (EXPECT(PLAYER != nil && mass> 0 && mass != [PLAYER baseMass]))
8129 {
8130 rate = calcFuelChargeRate(mass);
8131 }
8132
8133 OOLog(@"fuelPrices", @"\"%@\" fuel charge rate: %.2f (mass ratio: %.2f/%.2f)", [self shipDataKey], rate, mass, [PLAYER baseMass]);
8134#endif
8135
8136 return rate;
8137}

◆ generateMissileEquipmentTypeFrom:

- (OOEquipmentType *) generateMissileEquipmentTypeFrom: (NSString *)  role
implementation

Provided by category ShipEntity(Private).

Definition at line 2092 of file ShipEntity.m.

3327 :(NSString *)role
3328{
3329 /* The generated missile equipment type provides for backward compatibility with pre-1.74 OXPs missile_roles
3330 and follows this template:
3331
3332 //NPC equipment, incompatible with player ship. Not buyable because of its TL.
3333 (
3334 100, 100000, "Missile",
3335 "EQ_X_MISSILE",
3336 "Unidentified missile type.",
3337 {
3338 is_external_store = true;
3339 }
3340 )
3341 */
3342 NSArray *itemInfo = [NSArray arrayWithObjects:@"100", @"100000", @"Missile", role, @"Unidentified missile type.",
3343 [NSDictionary dictionaryWithObjectsAndKeys: @"true", @"is_external_store", nil], nil];
3344
3347}
void addEquipmentWithInfo:(NSArray *itemInfo)

◆ getAI

- (AI *) getAI

Definition at line 7616 of file ShipEntity.m.

8012{
8013 return shipAI;
8014}

Referenced by ShipExitAI(), ShipGetProperty(), and ShipSetProperty().

+ Here is the caller graph for this function:

◆ getDemoStartTime

- (OOTimeAbsolute) getDemoStartTime
implementation

Definition at line 14062 of file ShipEntity.m.

14613{
14614 return demoStartTime;
14615}
OOTimeAbsolute demoStartTime
Definition ShipEntity.h:495

◆ getDestroyedBy:damageType:

- (void) getDestroyedBy: (Entity *)  whom
damageType: (OOShipDamageType type 

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

9032 :(Entity *)whom damageType:(OOShipDamageType)type
9033{
9034 [self noteKilledBy:whom damageType:type];
9035 [self abortDocking];
9036 [self becomeExplosion];
9037}
OOShipDamageType
Definition ShipEntity.h:183

◆ getJSClass:andPrototype:

- (void) getJSClass: (JSClass **)  outClass
andPrototype: (JSObject **)  outPrototype 
implementation

Reimplemented from Entity.

Reimplemented in DockEntity, and StationEntity.

Provided by category ShipEntity(OOJavaScriptExtensions).

Definition at line 1 of file EntityOOJavaScriptExtensions.m.

121 :(JSClass **)outClass andPrototype:(JSObject **)outPrototype
122{
123 *outClass = JSShipClass();
124 *outPrototype = JSShipPrototype();
125}
JSObject * JSShipPrototype(void)
Definition OOJSShip.m:601
JSClass * JSShipClass(void)
Definition OOJSShip.m:595

◆ getTractoredBy:

- (void) getTractoredBy: (ShipEntity *)  other

Definition at line 9589 of file ShipEntity.m.

12874 :(ShipEntity *)other
12875{
12876 if([self status] == STATUS_BEING_SCOOPED) return; // both cargo and ship call this. Act only once.
12877 desired_speed = 0.0;
12878 [self setAITo:@"nullAI.plist"]; // prevent AI from changing status or behaviour.
12879 behaviour = BEHAVIOUR_TRACTORED;
12880 [self setStatus:STATUS_BEING_SCOOPED];
12881 [self addTarget:other];
12882 [self setOwner:other];
12883 // should we make this an all rather than first 16? - CIM
12884 // made it ignore other cargopods and similar at least. - CIM 28/7/2013
12885 [self checkScannerIgnoringUnpowered];
12886 unsigned i;
12887 ShipEntity *scooper;
12888 for (i = 0; i < n_scanned_ships ; i++)
12889 {
12890 scooper = (ShipEntity *)scanned_ships[i];
12891 // 'Dibs!' - Stops other ships from trying to scoop/shoot this cargo.
12892 if (other != scooper && (id) self == [scooper primaryTarget])
12893 {
12894 [scooper noteLostTarget];
12895 }
12896 }
12897}
void noteLostTarget()

◆ getWeaponOffsetFrom:withKey:inMode:

- (NSArray *) getWeaponOffsetFrom: (NSDictionary *)  dict
withKey: (NSString *)  key
inMode: (NSString *)  mode 

Definition at line 14942 of file ShipEntity.m.

2000 :(NSDictionary *)dict withKey:(NSString *)key inMode:(NSString *)mode
2001{
2002 Vector offset;
2003 if ([mode isEqualToString:@"single"])
2004 {
2005 offset = vector_multiply_scalar([dict oo_vectorForKey:key defaultValue:kZeroVector],_scaleFactor);
2006 return [NSArray arrayWithObject:MAKE_VECTOR_ARRAY(offset)];
2007 }
2008 else
2009 {
2010 NSArray *offsets = [dict oo_arrayForKey:key defaultValue:nil];
2011 if (offsets == nil) {
2013 return [NSArray arrayWithObject:MAKE_VECTOR_ARRAY(offset)];
2014 }
2015 NSMutableArray *output = [NSMutableArray arrayWithCapacity:[offsets count]];
2016 NSUInteger i;
2017 for (i=0;i<[offsets count];i++) {
2018 offset = vector_multiply_scalar([offsets oo_vectorAtIndex:i defaultValue:kZeroVector],_scaleFactor);
2019 [output addObject:MAKE_VECTOR_ARRAY(offset)];
2020 }
2021 return [NSArray arrayWithArray:output];
2022 }
2023}
GLfloat _scaleFactor
Definition ShipEntity.h:388
const char int mode
Definition ioapi.h:133

◆ getWitchspaceEntryCoordinates

- (void) getWitchspaceEntryCoordinates
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1184{
1185 /*- calculates coordinates from the nearest station it can find, or just fly 10s forward -*/
1186 if (!UNIVERSE)
1187 {
1188 Vector vr = vector_multiply_scalar(v_forward, maxFlightSpeed * 10.0); // 10 second flying away
1189 coordinates = HPvector_add(position, vectorToHPVector(vr));
1190 return;
1191 }
1192 //
1193 // find the nearest station...
1194 //
1195 // we don't use "checkScanner" because we must rely on finding a present station.
1196 //
1197 StationEntity *station = nil;
1198 station = [UNIVERSE nearestShipMatchingPredicate:IsStationPredicate
1199 parameter:nil
1200 relativeToEntity:self];
1201
1202 if (station && HPdistance2([station position], position) < SCANNER_MAX_RANGE2) // there is a station in range.
1203 {
1204 Vector vr = vector_multiply_scalar([station rightVector], 10000); // 10km from station
1205 coordinates = HPvector_add([station position], vectorToHPVector(vr));
1206 }
1207 else
1208 {
1209 Vector vr = vector_multiply_scalar(v_forward, maxFlightSpeed * 10.0); // 10 second flying away
1210 coordinates = HPvector_add(position, vectorToHPVector(vr));
1211 }
1212}

◆ group

- (OOShipGroup *) group

Definition at line 6493 of file ShipEntity.m.

6906{
6907 return _group;
6908}

Referenced by ShipGetProperty(), and ShipGroupAddShip().

+ Here is the caller graph for this function:

◆ groupAttackTarget

- (void) groupAttackTarget

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

340{
341 ShipEntity *target = nil, *ship = nil;
342
343 target = [self primaryTarget];
344
345 if (target == nil) return;
346
347 if ([self group] == nil) // ship is alone!
348 {
349 [self setFoundTarget:target];
350 [shipAI reactToMessage:@"GROUP_ATTACK_TARGET" context:@"groupAttackTarget"];
351 [self doScriptEvent:OOJSID("helpRequestReceived") withArgument:self andArgument:target];
352 return;
353 }
354
355 foreach (ship, [[self group] mutationSafeEnumerator])
356 {
357 [ship setFoundTarget:target];
358 [ship reactToAIMessage:@"GROUP_ATTACK_TARGET" context:@"groupAttackTarget"];
359 [ship doScriptEvent:OOJSID("helpRequestReceived") withArgument:self andArgument:target];
360
361 if ([ship escortGroup] != [ship group] && [[ship escortGroup] count] > 1) // Ship has a seperate escort group.
362 {
363 ShipEntity *escort = nil;
364 NSArray *escortMembers = [[ship escortGroup] memberArrayExcludingLeader];
365 foreach (escort, escortMembers)
366 {
367 [escort setFoundTarget:target];
368 [escort reactToAIMessage:@"GROUP_ATTACK_TARGET" context:@"groupAttackTarget"];
369 [escort doScriptEvent:OOJSID("helpRequestReceived") withArgument:self andArgument:target];
370 }
371 }
372 }
373}

◆ hasAllEquipment:

- (BOOL) hasAllEquipment: (id)  equipmentKeys

Definition at line 2092 of file ShipEntity.m.

3200 :(id)equipmentKeys
3201{
3202 return [self hasAllEquipment:equipmentKeys includeWeapons:NO whileLoading:NO];
3203}

◆ hasAllEquipment:includeWeapons:whileLoading:

- (BOOL) hasAllEquipment: (id)  equipmentKeys
includeWeapons: (BOOL)  includeWeapons
whileLoading: (BOOL)  loading 

Definition at line 2092 of file ShipEntity.m.

3180 :(id)equipmentKeys includeWeapons:(BOOL)includeWeapons whileLoading:(BOOL)loading
3181{
3182 NSEnumerator *keyEnum = nil;
3183 id key = nil;
3184
3185 if (_equipment == nil) return NO;
3186
3187 // Make sure it's an array or set, using a single-object set if it's a string.
3188 if ([equipmentKeys isKindOfClass:[NSString class]]) equipmentKeys = [NSArray arrayWithObject:equipmentKeys];
3189 else if (![equipmentKeys isKindOfClass:[NSArray class]] && ![equipmentKeys isKindOfClass:[NSSet class]]) return NO;
3190
3191 for (keyEnum = [equipmentKeys objectEnumerator]; (key = [keyEnum nextObject]); )
3192 {
3193 if (![self hasOneEquipmentItem:key includeWeapons:includeWeapons whileLoading:loading]) return NO;
3194 }
3195
3196 return YES;
3197}

◆ hasAutoAI

- (BOOL) hasAutoAI

Definition at line 7616 of file ShipEntity.m.

8018{
8019 return [[self shipInfoDictionary] oo_fuzzyBooleanForKey:@"auto_ai" defaultValue:YES];
8020}

◆ hasAutoCloak

- (BOOL) hasAutoCloak

Definition at line 6493 of file ShipEntity.m.

6687{
6688 return cloakAutomatic;
6689}

◆ hasAutoWeapons

- (BOOL) hasAutoWeapons

Definition at line 7616 of file ShipEntity.m.

8030{
8031 return [[self shipInfoDictionary] oo_fuzzyBooleanForKey:@"auto_weapons" defaultValue:NO];
8032}

◆ hasCargoScoop

- (BOOL) hasCargoScoop

Definition at line 2092 of file ShipEntity.m.

3959{
3960 return [self hasEquipmentItemProviding:@"EQ_CARGO_SCOOPS"];
3961}

◆ hasCascadeMine

- (BOOL) hasCascadeMine

Definition at line 2092 of file ShipEntity.m.

4031{
4032 /* TODO: this could be providing since theoretically OXP
4033 * deployable mines could also do cascade effects, but there are
4034 * probably better ways to manage OXP pylon AI */
4035 return [self hasEquipmentItem:@"EQ_QC_MINE" includeWeapons:YES whileLoading:NO];
4036}

◆ hasCloakingDevice

- (BOOL) hasCloakingDevice

Definition at line 2092 of file ShipEntity.m.

3971{
3972 /* TODO: Checks above stop this being 'providing'. */
3973 return [self hasEquipmentItem:@"EQ_CLOAKING_DEVICE"];
3974}

◆ hasDockingComputer

- (BOOL) hasDockingComputer

Definition at line 2092 of file ShipEntity.m.

4046{
4047 return [self hasEquipmentItemProviding:@"EQ_DOCK_COMP"];
4048}

◆ hasECM

- (BOOL) hasECM

Definition at line 2092 of file ShipEntity.m.

3965{
3966 return [self hasEquipmentItemProviding:@"EQ_ECM"];
3967}

◆ hasEquipmentItem:

- (BOOL) hasEquipmentItem: (id)  equipmentKeys

Definition at line 2092 of file ShipEntity.m.

3128 :(id)equipmentKeys
3129{
3130 return [self hasEquipmentItem:equipmentKeys includeWeapons:NO whileLoading:NO];
3131}

Referenced by ShipAwardEquipment(), and ShipSetEquipmentStatus().

+ Here is the caller graph for this function:

◆ hasEquipmentItem:includeWeapons:whileLoading:

- (BOOL) hasEquipmentItem: (id)  equipmentKeys
includeWeapons: (BOOL)  includeWeapons
whileLoading: (BOOL)  loading 

Definition at line 2092 of file ShipEntity.m.

3106 :(id)equipmentKeys includeWeapons:(BOOL)includeWeapons whileLoading:(BOOL)loading
3107{
3108 // this method is also used internally to find out if an equipped item is undamaged.
3109 if ([equipmentKeys isKindOfClass:[NSString class]])
3110 {
3111 return [self hasOneEquipmentItem:equipmentKeys includeWeapons:includeWeapons whileLoading:loading];
3112 }
3113 else
3114 {
3115 NSParameterAssert([equipmentKeys isKindOfClass:[NSArray class]] || [equipmentKeys isKindOfClass:[NSSet class]]);
3116
3117 id key = nil;
3118 foreach (key, equipmentKeys)
3119 {
3120 if ([self hasOneEquipmentItem:key includeWeapons:includeWeapons whileLoading:loading]) return YES;
3121 }
3122 }
3123
3124 return NO;
3125}

◆ hasEquipmentItemProviding:

- (BOOL) hasEquipmentItemProviding: (NSString *)  equipmentType

Definition at line 2092 of file ShipEntity.m.

3136 :(NSString *)equipmentType
3137{
3138 NSString *key = nil;
3139 foreach (key, _equipment) {
3140 if ([key isEqualToString:equipmentType])
3141 {
3142 // equipment always provides itself
3143 return YES;
3144 }
3145 else
3146 {
3148 if (et != nil && [et provides:equipmentType])
3149 {
3150 return YES;
3151 }
3152 }
3153 }
3154 return NO;
3155}

Referenced by ProxyPlayerEntity::alertCondition.

+ Here is the caller graph for this function:

◆ hasEscapePod

- (BOOL) hasEscapePod

Definition at line 2092 of file ShipEntity.m.

4040{
4041 return [self hasEquipmentItemProviding:@"EQ_ESCAPE_POD"];
4042}

◆ hasEscorts

- (BOOL) hasEscorts

Definition at line 6493 of file ShipEntity.m.

6974{
6975 if (_escortGroup == nil) return NO;
6976 return [_escortGroup count] > 1; // If only one member, it's self.
6977}

◆ hasExpandedCargoBay

- (BOOL) hasExpandedCargoBay

Definition at line 2092 of file ShipEntity.m.

3998{
3999 /* Not 'providing' - controlled through scripts */
4000 return [self hasEquipmentItem:@"EQ_CARGO_BAY"];
4001}

◆ hasFuelInjection

- (BOOL) hasFuelInjection

Definition at line 2092 of file ShipEntity.m.

4025{
4026 return [self hasEquipmentItemProviding:@"EQ_FUEL_INJECTION"];
4027}

◆ hasFuelScoop

- (BOOL) hasFuelScoop

Definition at line 2092 of file ShipEntity.m.

3952{
3953 return [self hasEquipmentItemProviding:@"EQ_FUEL_SCOOPS"];
3954}

◆ hasGalacticHyperdrive

- (BOOL) hasGalacticHyperdrive

Definition at line 2092 of file ShipEntity.m.

4052{
4053 return [self hasEquipmentItemProviding:@"EQ_GAL_DRIVE"];
4054}

◆ hasHeatShield

- (BOOL) hasHeatShield

Definition at line 2092 of file ShipEntity.m.

4019{
4020 return [self hasEquipmentItemProviding:@"EQ_HEAT_SHIELD"];
4021}

◆ hasHostileTarget

- (BOOL) hasHostileTarget

Reimplemented in PlayerEntity, and StationEntity.

Definition at line 7408 of file ShipEntity.m.

7443{
7444 Entity *t = [self primaryTarget];
7445 if (t == nil || ![t isShip])
7446 {
7447 return NO;
7448 }
7449 if ([self isMissile])
7450 {
7451 return YES; // missiles are always fired against a hostile target
7452 }
7453 if ((behaviour == BEHAVIOUR_AVOID_COLLISION)&&(previousCondition))
7454 {
7455 int old_behaviour = [previousCondition oo_intForKey:@"behaviour"];
7456 return IsBehaviourHostile(old_behaviour);
7457 }
7459}
static BOOL IsBehaviourHostile(OOBehaviour behaviour)

Referenced by HeadUpDisplay::hudDrawReticleOnTarget.

+ Here is the caller graph for this function:

◆ hasHyperspaceMotor

- (BOOL) hasHyperspaceMotor

Definition at line 2092 of file ShipEntity.m.

3207{
3208 return hyperspaceMotorSpinTime >= 0;
3209}
float hyperspaceMotorSpinTime
Definition ShipEntity.h:247

◆ hasMilitaryJammer

- (BOOL) hasMilitaryJammer

Definition at line 2092 of file ShipEntity.m.

3988{
3989#if USEMASC
3990 return [self hasEquipmentItemProviding:@"EQ_MILITARY_JAMMER"];
3991#else
3992 return NO;
3993#endif
3994}

◆ hasMilitaryScannerFilter

- (BOOL) hasMilitaryScannerFilter

Definition at line 2092 of file ShipEntity.m.

3978{
3979#if USEMASC
3980 return [self hasEquipmentItemProviding:@"EQ_MILITARY_SCANNER_FILTER"];
3981#else
3982 return NO;
3983#endif
3984}

◆ hasMilitaryShieldEnhancer

- (BOOL) hasMilitaryShieldEnhancer

Definition at line 2092 of file ShipEntity.m.

4012{
4013 /* Not 'providing' - controlled through scripts */
4014 return [self hasEquipmentItem:@"EQ_NAVAL_SHIELD_BOOSTER"];
4015}

◆ hasNewAI

- (BOOL) hasNewAI

Definition at line 7616 of file ShipEntity.m.

8024{
8025 return [[[self getAI] name] isEqualToString:@"nullAI.plist"];
8026}

◆ hasOneEquipmentItem:includeMissiles:whileLoading:

- (BOOL) hasOneEquipmentItem: (NSString *)  itemKey
includeMissiles: (BOOL)  includeMissiles
whileLoading: (BOOL)  loading 

Definition at line 2092 of file ShipEntity.m.

3045 :(NSString *)itemKey includeMissiles:(BOOL)includeMissiles whileLoading:(BOOL)loading
3046{
3047 if ([_equipment containsObject:itemKey]) return YES;
3048
3049 if (loading)
3050 {
3051 NSString *damaged = [itemKey stringByAppendingString:@"_DAMAGED"];
3052 if ([_equipment containsObject:damaged]) return YES;
3053 }
3054
3055 if (includeMissiles && missiles > 0)
3056 {
3057 unsigned i;
3058 if ([itemKey isEqualToString:@"thargon"]) itemKey = @"EQ_THARGON";
3059 for (i = 0; i < missiles; i++)
3060 {
3061 if (missile_list[i] != nil && [[missile_list[i] identifier] isEqualTo:itemKey]) return YES;
3062 }
3063 }
3064
3065 return NO;
3066}

Referenced by ShipRemoveEquipment().

+ Here is the caller graph for this function:

◆ hasOneEquipmentItem:includeWeapons:whileLoading:

- (BOOL) hasOneEquipmentItem: (NSString *)  itemKey
includeWeapons: (BOOL)  includeMissiles
whileLoading: (BOOL)  loading 

Definition at line 2092 of file ShipEntity.m.

3021 :(NSString *)itemKey includeWeapons:(BOOL)includeWeapons whileLoading:(BOOL)loading
3022{
3023 if ([self hasOneEquipmentItem:itemKey includeMissiles:includeWeapons whileLoading:loading]) return YES;
3024
3025 if (loading)
3026 {
3027 NSString *damaged = [itemKey stringByAppendingString:@"_DAMAGED"];
3028 if ([_equipment containsObject:damaged]) return YES;
3029 }
3030
3031 if (includeWeapons)
3032 {
3033 // Check for primary weapon
3035 if (!isWeaponNone(weaponType))
3036 {
3037 if ([self hasPrimaryWeapon:weaponType]) return YES;
3038 }
3039 }
3040
3041 return NO;
3042}
OOWeaponType OOWeaponTypeFromEquipmentIdentifierStrict(NSString *string) PURE_FUNC

◆ hasPrimaryRole:

- (BOOL) hasPrimaryRole: (NSString *)  role

Definition at line 6493 of file ShipEntity.m.

7324 :(NSString *)role
7325{
7326 return [[self primaryRole] isEqual:role];
7327}

◆ hasPrimaryWeapon:

- (BOOL) hasPrimaryWeapon: (OOWeaponType weaponType

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3069 :(OOWeaponType)weaponType
3070{
3071 NSEnumerator *subEntEnum = nil;
3072 ShipEntity *subEntity = nil;
3073
3074 if ([[forward_weapon_type identifier] isEqualToString:[weaponType identifier]] ||
3075 [[aft_weapon_type identifier] isEqualToString:[weaponType identifier]] ||
3076 [[port_weapon_type identifier] isEqualToString:[weaponType identifier]] ||
3077 [[starboard_weapon_type identifier] isEqualToString:[weaponType identifier]])
3078 {
3079 return YES;
3080 }
3081
3082 for (subEntEnum = [self shipSubEntityEnumerator]; (subEntity = [subEntEnum nextObject]); )
3083 {
3084 if ([subEntity hasPrimaryWeapon:weaponType]) return YES;
3085 }
3086
3087 return NO;
3088}

◆ hasProximityAlertIgnoringTarget:

- (BOOL) hasProximityAlertIgnoringTarget: (BOOL)  ignore_target

Definition at line 9589 of file ShipEntity.m.

11267 :(BOOL)ignore_target
11268{
11269 if (([self proximityAlert] != nil)&&(!ignore_target || ([self proximityAlert] != [self primaryTarget])))
11270 {
11271 return YES;
11272 }
11273 return NO;
11274}

◆ hasRole:

- (BOOL) hasRole: (NSString *)  role

Definition at line 6493 of file ShipEntity.m.

7250 :(NSString *)role
7251{
7252 return [roleSet hasRole:role] || [role isEqual:primaryRole] || [role isEqual:[self shipDataKeyAutoRole]];
7253}

◆ hasScoop

- (BOOL) hasScoop

Definition at line 2092 of file ShipEntity.m.

3946{
3947 return [self hasEquipmentItemProviding:@"EQ_FUEL_SCOOPS"] || [self hasEquipmentItemProviding:@"EQ_CARGO_SCOOPS"];
3948}

Referenced by ProxyPlayerEntity::alertCondition.

+ Here is the caller graph for this function:

◆ hasShieldBooster

- (BOOL) hasShieldBooster

Definition at line 2092 of file ShipEntity.m.

4005{
4006 /* Not 'providing' - controlled through scripts */
4007 return [self hasEquipmentItem:@"EQ_SHIELD_BOOSTER"];
4008}

◆ hasSubEntity:

- (BOOL) hasSubEntity: (Entity<OOSubEntity> *)  sub

Definition at line 14942 of file ShipEntity.m.

1325 :(Entity<OOSubEntity> *)sub
1326{
1327 return [subEntities containsObject:sub];
1328}

◆ heatInsulation

- (GLfloat) heatInsulation

Definition at line 7616 of file ShipEntity.m.

8819{
8820 return _heatInsulation;
8821}
float _heatInsulation
Definition ShipEntity.h:462

◆ homeSystem

- (OOSystemID) homeSystem

Definition at line 7616 of file ShipEntity.m.

7903{
7904 return home_system;
7905}
OOSystemID home_system
Definition ShipEntity.h:379

◆ hullHeatLevel

- (GLfloat) hullHeatLevel

Definition at line 9589 of file ShipEntity.m.

9755{
9756 GLfloat result = (GLfloat)ship_temperature / (GLfloat)SHIP_MAX_CABIN_TEMP;
9757 return OOClamp_0_1_f(result);
9758}
#define SHIP_MAX_CABIN_TEMP
Definition ShipEntity.h:67

◆ hyperspaceSpinTime

- (float) hyperspaceSpinTime

Definition at line 2092 of file ShipEntity.m.

3213{
3215}

◆ identFromShip:

- (NSString *) identFromShip: (ShipEntity*)  otherShip

Definition at line 6493 of file ShipEntity.m.

7240 :(ShipEntity*) otherShip
7241{
7242 if ([self isJammingScanning] && ![otherShip hasMilitaryScannerFilter])
7243 {
7244 return DESC(@"unknown-target");
7245 }
7246 return [self displayName];
7247}
#define DESC(key)
Definition Universe.h:848

◆ increase_flight_pitch:

- (void) increase_flight_pitch: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8662 :(double) delta
8663{
8664 flightPitch += delta;
8667 else if (flightPitch < -max_flight_pitch)
8669}

◆ increase_flight_roll:

- (void) increase_flight_roll: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8642 :(double) delta
8643{
8644 flightRoll += delta;
8647 else if (flightRoll < -max_flight_roll)
8649}

◆ increase_flight_speed:

- (void) increase_flight_speed: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8611 :(double) delta
8612{
8613 double factor = 1.0;
8614 if (desired_speed > maxFlightSpeed && [self hasFuelInjection] && fuel > MIN_FUEL) factor = [self afterburnerFactor];
8615
8616 if (flightSpeed < maxFlightSpeed * factor)
8617 flightSpeed += delta * factor;
8618 else
8619 flightSpeed = maxFlightSpeed * factor;
8620}
BOOL hasFuelInjection()

◆ increase_flight_yaw:

- (void) increase_flight_yaw: (double)  delta

Definition at line 7616 of file ShipEntity.m.

8682 :(double) delta
8683{
8684 flightYaw += delta;
8687 else if (flightYaw < -max_flight_yaw)
8689}

◆ init

- (id) init
implementation

Reimplemented from Entity.

Reimplemented in PlayerEntity.

Definition at line 14942 of file ShipEntity.m.

176{
177 /* -init used to set up a bunch of defaults that were different from
178 those in -reinit and -setUpShipFromDictionary:. However, it seems that
179 no ships are ever used which are not -setUpShipFromDictionary: (which
180 is as it should be), so these different defaults were meaningless.
181 */
182 return [self initWithKey:@"" definition:nil];
183}

◆ initBypassForPlayer

- (id) initBypassForPlayer
implementation

Provided by category ShipEntity(Hax).

Definition at line 14942 of file ShipEntity.m.

187{
188 return [super init];
189}

◆ initWithKey:definition:

- (id) initWithKey: (NSString *)  key
definition: (NSDictionary *)  dict 

Reimplemented in DockEntity, ProxyPlayerEntity, and StationEntity.

Definition at line 14942 of file ShipEntity.m.

193 :(NSString *)key definition:(NSDictionary *)dict
194{
196
197 NSParameterAssert(dict != nil);
198
199 self = [super init];
200 if (self == nil) return nil;
201
202 _shipKey = [key retain];
203
204 isShip = YES;
206 [self setStatus:STATUS_IN_FLIGHT];
207
212 weapon_temp = 0.0f;
214 forward_weapon_temp = 0.0f;
215 aft_weapon_temp = 0.0f;
216 port_weapon_temp = 0.0f;
218
219 _nextAegisCheck = -0.1f;
221
222 if (![self setUpShipFromDictionary:dict])
223 {
224 [self release];
225 self = nil;
226 }
227
228 // Problem observed in testing -- Ahruman
229 if (self != nil && !isfinite(maxFlightSpeed))
230 {
231 OOLog(@"ship.sanityCheck.failed", @"Ship %@ %@ infinite top speed, clamped to 300.", self, @"generated with");
232 maxFlightSpeed = 300;
233 }
234 return self;
235
237}
#define OOJS_PROFILE_EXIT
#define OOJS_PROFILE_ENTER
#define INITIAL_SHOT_TIME
Definition ShipEntity.h:100
#define SHIP_MIN_CABIN_TEMP
Definition ShipEntity.h:68
GLfloat zero_distance
Definition Entity.h:108
OOTimeDelta shot_time
Definition ShipEntity.h:197

Referenced by ProxyPlayerEntity::alertCondition.

+ Here is the caller graph for this function:

◆ interpretAIMessage:

- (void) interpretAIMessage: (NSString *)  message

Reimplemented in PlayerEntity.

Definition at line 14062 of file ShipEntity.m.

14270 :(NSString *)ms
14271{
14272 if ([ms hasPrefix:AIMS_AGGRESSOR_SWITCHED_TARGET])
14273 {
14274 // if I'm under attack send a thank-you message to the rescuer
14275 //
14276 NSArray* tokens = ScanTokensFromString(ms);
14277 int switcher_id = [(NSString*)[tokens objectAtIndex:1] intValue]; // Attacker that switched targets.
14278 Entity* switcher = [UNIVERSE entityForUniversalID:switcher_id];
14279 int rescuer_id = [(NSString*)[tokens objectAtIndex:2] intValue]; // New primary target of attacker.
14280 Entity* rescuer = [UNIVERSE entityForUniversalID:rescuer_id];
14281 if ((switcher == [self primaryAggressor])&&(switcher == [self primaryTarget])&&(switcher)&&(rescuer)&&(rescuer->isShip)&&([self thankedShip] != rescuer)&&(scanClass != CLASS_THARGOID))
14282 {
14283 ShipEntity* rescueShip = (ShipEntity*)rescuer;
14284// ShipEntity* switchingShip = (ShipEntity*)switcher;
14285 if (scanClass == CLASS_POLICE)
14286 {
14287 [self sendExpandedMessage:@"[police-thanks-for-assist]" toShip:rescueShip];
14288 [rescueShip setBounty:[rescueShip bounty] * 0.80 withReason:kOOLegalStatusReasonAssistingPolice]; // lower bounty by 20%
14289 }
14290 else
14291 {
14292 [self sendExpandedMessage:@"[thanks-for-assist]" toShip:rescueShip];
14293 }
14294 [self setThankedShip:rescuer];
14295 }
14296 }
14297}
NSMutableArray * ScanTokensFromString(NSString *values)
#define AIMS_AGGRESSOR_SWITCHED_TARGET
Definition ShipEntity.h:94
Entity * thankedShip()

◆ isBeacon

- (BOOL) isBeacon
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1596{
1597 return [self beaconCode] != nil;
1598}

◆ IsBehaviourHostile

+ (static BOOL) IsBehaviourHostile (OOBehaviour behaviour
implementation

Definition at line 7408 of file ShipEntity.m.

7409{
7410 switch (behaviour)
7411 {
7412 case BEHAVIOUR_ATTACK_TARGET:
7413 case BEHAVIOUR_ATTACK_FLY_TO_TARGET:
7414 case BEHAVIOUR_ATTACK_FLY_FROM_TARGET:
7415 case BEHAVIOUR_RUNNING_DEFENSE:
7416 case BEHAVIOUR_FLEE_TARGET:
7417 case BEHAVIOUR_ATTACK_BREAK_OFF_TARGET:
7418 case BEHAVIOUR_ATTACK_SLOW_DOGFIGHT:
7419 case BEHAVIOUR_EVASIVE_ACTION:
7420 case BEHAVIOUR_FLEE_EVASIVE_ACTION:
7421 case BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX:
7422 // case BEHAVIOUR_ATTACK_MINING_TARGET:
7423 case BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE:
7424 case BEHAVIOUR_ATTACK_BROADSIDE:
7425 case BEHAVIOUR_ATTACK_BROADSIDE_LEFT:
7426 case BEHAVIOUR_ATTACK_BROADSIDE_RIGHT:
7427 case BEHAVIOUR_CLOSE_TO_BROADSIDE_RANGE:
7428 case BEHAVIOUR_CLOSE_WITH_TARGET:
7429 case BEHAVIOUR_ATTACK_SNIPER:
7430 case BEHAVIOUR_SCRIPTED_ATTACK_AI:
7431 return YES;
7432
7433 default:
7434 return NO;
7435 }
7436
7437 return 100 < behaviour && behaviour < 120;
7438}

◆ isBoulder

- (BOOL) isBoulder

Definition at line 14942 of file ShipEntity.m.

1667{
1668 return [roleSet hasRole:kBoulderRole];
1669}

◆ isCloaked

- (BOOL) isCloaked

Definition at line 6493 of file ShipEntity.m.

6668{
6670}

◆ isDefenseTarget:

- (BOOL) isDefenseTarget: (Entity *)  target

Definition at line 9589 of file ShipEntity.m.

11212 :(Entity *)target
11213{
11214 return [_defenseTargets containsObject:target];
11215}

◆ isDemoShip

- (BOOL) isDemoShip

◆ isEscort

- (BOOL) isEscort

Definition at line 6493 of file ShipEntity.m.

7373{
7374 return [UNIVERSE role:[self primaryRole] isInCategory:@"oolite-escort"];
7375}

◆ isExplicitlyUnpiloted

- (BOOL) isExplicitlyUnpiloted

Definition at line 6493 of file ShipEntity.m.

7397{
7398 return _explicitlyUnpiloted;
7399}
unsigned _explicitlyUnpiloted
Definition ShipEntity.h:274

◆ isFrangible

- (BOOL) isFrangible

◆ isFriendlyTo:

- (BOOL) isFriendlyTo: (ShipEntity *)  otherShip

Definition at line 9589 of file ShipEntity.m.

10151 :(ShipEntity *)otherShip
10152{
10153 BOOL isFriendly = NO;
10154 OOShipGroup *myGroup = [self group];
10155 OOShipGroup *otherGroup = [otherShip group];
10156
10157 if ((otherShip == self) ||
10158 ([self isPolice] && [otherShip isPolice]) ||
10159 ([self isThargoid] && [otherShip isThargoid]) ||
10160 (myGroup != nil && otherGroup != nil && (myGroup == otherGroup || [otherGroup leader] == self)) ||
10161 ([self scanClass] == CLASS_MILITARY && [otherShip scanClass] == CLASS_MILITARY))
10162 {
10163 isFriendly = YES;
10164 }
10165
10166 return isFriendly;
10167}
ShipEntity * leader()

◆ isHostileTo:

- (BOOL) isHostileTo: (Entity *)  entity

Definition at line 7408 of file ShipEntity.m.

7462 :(Entity *)entity
7463{
7464 return ([self hasHostileTarget] && [self primaryTarget] == entity);
7465}

◆ isHulk

- (BOOL) isHulk

◆ isJammingScanning

- (BOOL) isJammingScanning
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 6493 of file ShipEntity.m.

6699{
6700 return ([self hasMilitaryJammer] && military_jammer_active);
6701}
BOOL hasMilitaryJammer()

◆ isMinable

- (BOOL) isMinable

Definition at line 14942 of file ShipEntity.m.

1673{
1674 if ([self hasRole:@"asteroid"] || [self isBoulder])
1675 {
1676 if (!noRocks)
1677 {
1678 return YES;
1679 }
1680 }
1681 return NO;
1682}

◆ isMine

- (BOOL) isMine

Definition at line 6493 of file ShipEntity.m.

7361{
7362 return [[self primaryRole] hasSuffix:@"MINE"];
7363}

◆ isMining

- (BOOL) isMining

Reimplemented in PlayerEntity.

Definition at line 14062 of file ShipEntity.m.

14265{
14266 return ((behaviour == BEHAVIOUR_ATTACK_MINING_TARGET)&&([forward_weapon_type isMiningLaser]));
14267}

◆ isMissile

- (BOOL) isMissile

◆ isMissileFlagSet

- (BOOL) isMissileFlagSet

Definition at line 9589 of file ShipEntity.m.

12311{
12312 return isMissile; // were we created using fireMissile? (for tracking submunitions and preventing collisions at launch)
12313}

◆ isPirate

- (BOOL) isPirate

Definition at line 6493 of file ShipEntity.m.

7349{
7350 return [UNIVERSE role:[self primaryRole] isInCategory:@"oolite-pirate"];
7351}

◆ isPirateVictim

- (BOOL) isPirateVictim

Definition at line 6493 of file ShipEntity.m.

7391{
7392 return [UNIVERSE roleIsPirateVictim:[self primaryRole]];
7393}

◆ isPolice

- (BOOL) isPolice

Definition at line 6493 of file ShipEntity.m.

7331{
7332 //bounty hunters have a police role, but are not police, so we must test by scan class, not by role
7333 return [self scanClass] == CLASS_POLICE;
7334}

◆ isShipWithSubEntityShip:

- (BOOL) isShipWithSubEntityShip: (Entity *)  other
implementation

Reimplemented from Entity.

Provided by category ShipEntity(SubEntityRelationship).

Definition at line 14062 of file ShipEntity.m.

14862 :(Entity *)other
14863{
14864 assert ([self isShip]);
14865
14866 if (![other isShip]) return NO;
14867 if (![other isSubEntity]) return NO;
14868 if ([other owner] != self) return NO;
14869
14870#ifndef NDEBUG
14871 // Sanity check; this should always be true.
14872 if (![self hasSubEntity:(ShipEntity *)other])
14873 {
14874 OOLogERR(@"ship.subentity.sanityCheck.failed", @"%@ thinks it's a subentity of %@, but the supposed parent does not agree. %@", [other shortDescription], [self shortDescription], @"This is an internal error, please report it.");
14875 [other setOwner:nil];
14876 return NO;
14877 }
14878#endif
14879
14880 return YES;
14881}

◆ isShuttle

- (BOOL) isShuttle

Definition at line 6493 of file ShipEntity.m.

7379{
7380 return [UNIVERSE role:[self primaryRole] isInCategory:@"oolite-shuttle"];
7381}

◆ isTemplateCargoPod

- (BOOL) isTemplateCargoPod

Definition at line 14942 of file ShipEntity.m.

1018{
1019 return [[self primaryRole] isEqualToString:@"oolite-template-cargopod"];
1020}

◆ isThargoid

- (BOOL) isThargoid

Definition at line 6493 of file ShipEntity.m.

7337{
7338 return [self scanClass] == CLASS_THARGOID;
7339}

◆ isTrader

- (BOOL) isTrader

Definition at line 6493 of file ShipEntity.m.

7343{
7344 return [UNIVERSE role:[self primaryRole] isInCategory:@"oolite-trader"];
7345}

◆ isTurret

- (BOOL) isTurret

Definition at line 6493 of file ShipEntity.m.

7385{
7386 return behaviour == BEHAVIOUR_TRACK_AS_TURRET;
7387}

◆ isUnpiloted

- (BOOL) isUnpiloted

Reimplemented in StationEntity.

Definition at line 6493 of file ShipEntity.m.

7403{
7404 return [self isExplicitlyUnpiloted] || [self isHulk] || [self scanClass] == CLASS_ROCK || [self scanClass] == CLASS_CARGO;
7405}

◆ isValidTarget:

- (BOOL) isValidTarget: (Entity *)  target

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

10028 :(Entity *)target
10029{
10030 if (target == nil)
10031 {
10032 return NO;
10033 }
10034 if ([target isShip])
10035 {
10036 OOEntityStatus tstatus = [target status];
10037 if (tstatus == STATUS_ENTERING_WITCHSPACE || tstatus == STATUS_IN_HOLD || tstatus == STATUS_DOCKED || tstatus == STATUS_DEAD)
10038 // 2013-01-13, Eric: added STATUS_DEAD because I keep seeing ships locked on dead ships in attack mode.
10039 {
10040 return NO;
10041 }
10042 return YES;
10043 }
10044 if ([target isWormhole] && [target scanClass] != CLASS_NO_DRAW)
10045 {
10046 return YES;
10047 }
10048 return NO;
10049}
OOEntityStatus
Definition Entity.h:60
unsigned isWormhole
Definition Entity.h:94

◆ isVisible

- (BOOL) isVisible
implementation

Reimplemented from Entity.

Definition at line 14942 of file ShipEntity.m.

1590{
1592}

◆ isVisibleToScripts

- (BOOL) isVisibleToScripts
implementation

Reimplemented from Entity.

Provided by category ShipEntity(OOJavaScriptExtensions).

Definition at line 1 of file EntityOOJavaScriptExtensions.m.

116{
117 return YES;
118}

◆ isWeapon

- (BOOL) isWeapon

Definition at line 6493 of file ShipEntity.m.

7367{
7368 return [self isMissile] || [self isMine];
7369}

◆ landOnPlanet

- (void) landOnPlanet
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1348{
1349 // Selects the nearest planet it can find.
1350 [self landOnPlanet:[self findNearestPlanet]];
1351}

◆ landOnPlanet:

- (void) landOnPlanet: (OOPlanetEntity *)  planet

Definition at line 9589 of file ShipEntity.m.

14016 :(OOPlanetEntity *)planet
14017{
14018 if (planet && [self isShuttle])
14019 {
14020 [planet welcomeShuttle:self];
14021 }
14022 [self doScriptEvent:OOJSID("shipLandedOnPlanet") withArgument:planet andReactToAIMessage:@"LANDED_ON_PLANET"];
14023
14024#ifndef NDEBUG
14025 if ([self reportAIMessages])
14026 {
14027 OOLog(@"planet.collide.shuttleLanded", @"DEBUG: %@ landed on planet %@", self, planet);
14028 }
14029#endif
14030
14031 [UNIVERSE removeEntity:self];
14032}
void welcomeShuttle:(ShipEntity *shuttle)
BOOL isShuttle()

◆ laserColor

- (OOColor *) laserColor

Definition at line 9589 of file ShipEntity.m.

11711{
11712 return [[laser_color retain] autorelease];
11713}

◆ laserHeatLevel

- (GLfloat) laserHeatLevel

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

9706{
9707 GLfloat result = weapon_temp / NPC_MAX_WEAPON_TEMP;
9708 return OOClamp_0_1_f(result);
9709}

◆ laserHeatLevelAft

- (GLfloat) laserHeatLevelAft

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

9713{
9714 GLfloat result = aft_weapon_temp / NPC_MAX_WEAPON_TEMP;
9715 return OOClamp_0_1_f(result);
9716}

◆ laserHeatLevelForward

- (GLfloat) laserHeatLevelForward

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

9720{
9721 GLfloat result = forward_weapon_temp / NPC_MAX_WEAPON_TEMP;
9723 { // must check subents
9724 OOWeaponType forward_weapon_real_type = nil;
9725 NSEnumerator *subEnum = [self shipSubEntityEnumerator];
9726 ShipEntity *se = nil;
9727 while (isWeaponNone(forward_weapon_real_type) && (se = [subEnum nextObject]))
9728 {
9730 {
9731 forward_weapon_real_type = se->forward_weapon_type;
9733 }
9734 }
9735 }
9736 return OOClamp_0_1_f(result);
9737}

◆ laserHeatLevelPort

- (GLfloat) laserHeatLevelPort

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

9741{
9742 GLfloat result = port_weapon_temp / NPC_MAX_WEAPON_TEMP;
9743 return OOClamp_0_1_f(result);
9744}

◆ laserHeatLevelStarboard

- (GLfloat) laserHeatLevelStarboard

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

9748{
9749 GLfloat result = starboard_weapon_temp / NPC_MAX_WEAPON_TEMP;
9750 return OOClamp_0_1_f(result);
9751}

◆ laserPortOffset:

- (NSArray *) laserPortOffset: (OOWeaponFacing direction

Definition at line 9589 of file ShipEntity.m.

11911 :(OOWeaponFacing)direction
11912{
11913 NSArray *laserPortOffset = nil;
11914 switch (direction)
11915 {
11917 case WEAPON_FACING_NONE:
11918 laserPortOffset = forwardWeaponOffset;
11919 break;
11920
11921 case WEAPON_FACING_AFT:
11922 laserPortOffset = aftWeaponOffset;
11923 break;
11924
11925 case WEAPON_FACING_PORT:
11926 laserPortOffset = portWeaponOffset;
11927 break;
11928
11930 laserPortOffset = starboardWeaponOffset;
11931 break;
11932 }
11933 return laserPortOffset;
11934}

◆ lastAegisLock

- (Entity< OOStellarBody > *) lastAegisLock
implementation

Provided by category ShipEntity(Private).

Definition at line 7616 of file ShipEntity.m.

7883{
7884 Entity<OOStellarBody> *stellar = [_lastAegisLock weakRefUnderlyingObject];
7885 if (stellar == nil)
7886 {
7887 [_lastAegisLock release];
7889 }
7890
7891 return stellar;
7892}

◆ lastEscortTarget

- (Entity *) lastEscortTarget

Definition at line 9589 of file ShipEntity.m.

9951{
9952 Entity *result = [_lastEscortTarget weakRefUnderlyingObject];
9953 if (result == nil || ![self isValidTarget:result])
9954 {
9956 return nil;
9957 }
9958 return result;
9959}
OOWeakReference * _lastEscortTarget
Definition ShipEntity.h:441

◆ launchCascadeMine

- (BOOL) launchCascadeMine

Definition at line 9589 of file ShipEntity.m.

12379{
12380 if (![self hasCascadeMine]) return NO;
12381 [self setSpeed: maxFlightSpeed + 300];
12382 ShipEntity* bomb = [UNIVERSE newShipWithRole:@"energy-bomb"];
12383 if (bomb == nil) return NO;
12384
12385 [self removeEquipmentItem:@"EQ_QC_MINE"];
12386
12387 double start = collision_radius + bomb->collision_radius;
12388 Quaternion random_direction;
12389 Vector vel;
12390 HPVector rpos;
12391 double random_roll = randf() - 0.5; // -0.5 to +0.5
12392 double random_pitch = randf() - 0.5; // -0.5 to +0.5
12393 quaternion_set_random(&random_direction);
12394
12395 rpos = HPvector_subtract([self position], vectorToHPVector(vector_multiply_scalar(v_forward, start)));
12396
12397 double eject_speed = -800.0;
12398 vel = vector_multiply_scalar(v_forward, [self flightSpeed] + eject_speed);
12399 eject_speed *= 0.5 * (randf() - 0.5); // -0.25x .. +0.25x
12400 vel = vector_add(vel, vector_multiply_scalar(v_up, eject_speed));
12401 eject_speed *= 0.5 * (randf() - 0.5); // -0.0625x .. +0.0625x
12402 vel = vector_add(vel, vector_multiply_scalar(v_right, eject_speed));
12403
12404 [bomb setPosition:rpos];
12405 [bomb setOrientation:random_direction];
12406 [bomb setRoll:random_roll];
12407 [bomb setPitch:random_pitch];
12408 [bomb setVelocity:vel];
12409 [bomb setScanClass:CLASS_MINE];
12410 [bomb setEnergy:5.0]; // 5 second countdown
12411 [bomb setBehaviour:BEHAVIOUR_ENERGY_BOMB_COUNTDOWN];
12412 [bomb setOwner:self];
12413 [UNIVERSE addEntity:bomb]; // STATUS_IN_FLIGHT, AI state GLOBAL
12414 [bomb release];
12415
12417 {
12418 [self deactivateCloakingDevice];
12419 }
12420
12421 if (self != PLAYER) // get the heck out of here
12422 {
12423 [self addTarget:bomb];
12424 [self setBehaviour:BEHAVIOUR_FLEE_TARGET];
12425 frustration = 0.0;
12426 }
12427 return YES;
12428}
void setBehaviour:(OOBehaviour cond)

◆ launchEscapeCapsule

- (ShipEntity *) launchEscapeCapsule

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12432{
12433 ShipEntity *result = nil;
12434 ShipEntity *mainPod = nil;
12435 unsigned n_pods, i;
12436 NSMutableArray *passengers = nil;
12437
12438 /*
12439 CHANGE: both player & NPCs can now launch escape pods in interstellar
12440 space. -- Kaks 20101113
12441 */
12442
12443 // check number of pods aboard -- require at least one.
12444 n_pods = [shipinfoDictionary oo_unsignedIntForKey:@"has_escape_pod"];
12445 if (n_pods > 65) n_pods = 65; // maximum of 64 passengers.
12446 if (n_pods > 1) passengers = [NSMutableArray arrayWithCapacity:n_pods-1];
12447
12448 if (crew) // transfer crew
12449 {
12450 // make sure crew inherit any legalStatus
12451 for (i = 0; i < [crew count]; i++)
12452 {
12453 OOCharacter *ch = (OOCharacter*)[crew objectAtIndex:i];
12454 [ch setLegalStatus: [self legalStatus] | [ch legalStatus]];
12455 }
12456 mainPod = [self launchPodWithCrew:crew];
12457 if (mainPod)
12458 {
12459 result = mainPod;
12460 [self setCrew:nil];
12461 [self setHulk:YES]; // we are without crew now.
12462 }
12463 }
12464
12465 // launch other pods (passengers)
12466 for (i = 1; i < n_pods; i++)
12467 {
12468 ShipEntity *passenger = nil;
12469 passenger = [self launchPodWithCrew:[NSArray arrayWithObject:[OOCharacter randomCharacterWithRole:@"passenger" andOriginalSystem:gen_rnd_number()]]];
12470 [passengers addObject:passenger];
12471 }
12472
12473 if (mainPod) [self doScriptEvent:OOJSID("shipLaunchedEscapePod") withArgument:mainPod andArgument:passengers];
12474
12475 return result;
12476}
#define OOJSID(str)
Definition OOJSPropID.h:38
void setLegalStatus:(int value)
OOCharacter * randomCharacterWithRole:andOriginalSystem:(NSString *c_role,[andOriginalSystem] OOSystemID s)

◆ launchPatrol

- (BOOL) launchPatrol
implementation

Reimplemented in StationEntity.

Provided by category ShipEntity(OOAIStationStubs).

Definition at line 1 of file ShipEntityAI.m.

2935{
2936 OOLog(@"ai.invalid.notAStation", @"Attempt to use station AI method \"%s\" on non-station %@.", "launchPatrol", self);
2937 return NO;
2938}

◆ launchPodWithCrew:

- (ShipEntity *) launchPodWithCrew: (NSArray *)  podCrew
implementation

Provided by category ShipEntity(Private).

Definition at line 2092 of file ShipEntity.m.

2276 :(NSArray *)podCrew
2277{
2278 ShipEntity *pod = nil;
2279
2280 pod = [UNIVERSE newShipWithRole:[shipinfoDictionary oo_stringForKey:@"escape_pod_role"]]; // or nil
2281 if (!pod)
2282 {
2283 // _role not defined? it might have _model defined;
2284 pod = [UNIVERSE newShipWithRole:[shipinfoDictionary oo_stringForKey:@"escape_pod_model" defaultValue:@"escape-capsule"]];
2285 if (!pod)
2286 {
2287 pod = [UNIVERSE newShipWithRole:@"escape-capsule"];
2288 OOLog(@"shipEntity.noEscapePod", @"Ship %@ has no correct escape_pod_role defined. Now using default capsule.", self);
2289 }
2290 }
2291
2292 if (pod)
2293 {
2294 [pod setOwner:self];
2295 [pod setTemperature:[self randomEjectaTemperatureWithMaxFactor:0.9]];
2296 [pod setCommodity:@"slaves" andAmount:1];
2297 [pod setCrew:podCrew];
2298 [pod switchAITo:@"oolite-shuttleAI.js"];
2299 [self dumpItem:pod]; // CLASS_CARGO, STATUS_IN_FLIGHT, AI state GLOBAL
2300 [pod release]; //release
2301 }
2302
2303 return pod;
2304}
void setCrew:(NSArray *crewArray)
void switchAITo:(NSString *aiString)

◆ leaveDock:

- (void) leaveDock: (StationEntity *)  station

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

13468 :(StationEntity *)station
13469{
13470 // This code is never used. Currently npc ships are only launched from the stations launch queue.
13471 if (station == nil) return;
13472
13473 [station launchShip:self];
13474
13475}
void launchShip:(ShipEntity *ship)

◆ leaveWitchspace

- (void) leaveWitchspace

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

13533{
13534 Quaternion q1;
13536 Vector v1 = vector_forward_from_quaternion(q1);
13537 double d1 = 0.0;
13538
13539 GLfloat min_d1 = [UNIVERSE safeWitchspaceExitDistance];
13540
13541 while (fabs(d1) < min_d1)
13542 {
13543 // not scannerRange - has no effect on witchspace exit
13544 d1 = SCANNER_MAX_RANGE * (randf() - randf());
13545 }
13546
13547 HPVector exitposition = [UNIVERSE getWitchspaceExitPosition];
13548 exitposition.x += v1.x * d1; // randomise exit position
13549 exitposition.y += v1.y * d1;
13550 exitposition.z += v1.z * d1;
13551 [self setPosition:exitposition];
13552 [self witchspaceLeavingEffects];
13553}

◆ legalStatus

- (int) legalStatus

Definition at line 7616 of file ShipEntity.m.

8310{
8311 if (scanClass == CLASS_THARGOID)
8312 return 5 * collision_radius;
8313 if (scanClass == CLASS_ROCK)
8314 return 0;
8315 return (int)[self bounty];
8316}

◆ lightsActive

- (BOOL) lightsActive

Definition at line 9589 of file ShipEntity.m.

13661{
13662 return _lightsActive;
13663}
unsigned _lightsActive
Definition ShipEntity.h:282

◆ lookingAtSunWithThresholdAngleCos:

- (GLfloat) lookingAtSunWithThresholdAngleCos: (GLfloat)  thresholdAngleCos

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

11345 :(GLfloat) thresholdAngleCos
11346{
11347 OOSunEntity *sun = [UNIVERSE sun];
11348 GLfloat measuredCos = 999.0f, measuredCosAbs;
11349 GLfloat sunBrightness = 0.0f;
11350 Vector relativePosition, unitRelativePosition;
11351
11352 if (EXPECT_NOT(!sun)) return 0.0f;
11353
11354 relativePosition = HPVectorToVector(HPvector_subtract([self position], [sun position]));
11355 unitRelativePosition = vector_normal_or_zbasis(relativePosition);
11356 switch (currentWeaponFacing)
11357 {
11359 measuredCos = -dot_product(unitRelativePosition, v_forward);
11360 break;
11361 case WEAPON_FACING_AFT:
11362 measuredCos = +dot_product(unitRelativePosition, v_forward);
11363 break;
11364 case WEAPON_FACING_PORT:
11365 measuredCos = +dot_product(unitRelativePosition, v_right);
11366 break;
11368 measuredCos = -dot_product(unitRelativePosition, v_right);
11369 break;
11370 default:
11371 break;
11372 }
11373 measuredCosAbs = fabs(measuredCos);
11374 if (thresholdAngleCos <= measuredCosAbs && measuredCosAbs <= 1.0f) // angle from viewpoint to sun <= desired threshold
11375 {
11376 sunBrightness = (measuredCos - thresholdAngleCos) / (1.0f - thresholdAngleCos);
11377 if (sunBrightness < 0.0f) sunBrightness = 0.0f;
11378 }
11379 return sunBrightness * sunBrightness * sunBrightness;
11380}
Vector relativePosition()
Definition Entity.m:637

◆ manageCollisions

- (void) manageCollisions

Definition at line 9589 of file ShipEntity.m.

12636{
12637 // deal with collisions
12638 //
12639 Entity* ent;
12640 ShipEntity* other_ship;
12641
12642 while ([collidingEntities count] > 0)
12643 {
12644 // EMMSTRAN: investigate if doing this backwards would be more efficient. (Not entirely obvious, NSArray is kinda funky.) -- Ahruman 2011-02-12
12645 ent = [[[collidingEntities objectAtIndex:0] retain] autorelease];
12646 [collidingEntities removeObjectAtIndex:0];
12647 if (ent)
12648 {
12649 if ([ent isShip])
12650 {
12651 other_ship = (ShipEntity *)ent;
12652 [self collideWithShip:other_ship];
12653 }
12654 else if ([ent isStellarObject])
12655 {
12656 [self getDestroyedBy:ent damageType:[ent isSun] ? kOODamageTypeHitASun : kOODamageTypeHitAPlanet];
12657 if (self == PLAYER) [self retain];
12658 }
12659 else if ([ent isWormhole])
12660 {
12661 if( [self isPlayer] ) [self enterWormhole:(WormholeEntity*)ent];
12662 else [self enterWormhole:(WormholeEntity*)ent replacing:NO];
12663 }
12664 }
12665 }
12666}
BOOL isStellarObject()
Definition Entity.m:180

◆ markAsOffender:

- (void) markAsOffender: (int offence_value

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

13584 :(int)offence_value
13585{
13586 [self markAsOffender:offence_value withReason:kOOLegalStatusReasonUnknown];
13587}

◆ markAsOffender:withReason:

- (void) markAsOffender: (int offence_value
withReason: (OOLegalStatusReason reason 

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

13590 :(int)offence_value withReason:(OOLegalStatusReason)reason
13591{
13592 if (![self isPolice] && ![self isCloaked] && self != [UNIVERSE station])
13593 {
13594 if ([self isSubEntity])
13595 {
13596 [[self parentEntity] markAsOffender:offence_value withReason:reason];
13597 }
13598 else
13599 {
13600 if ((scanClass == CLASS_THARGOID || scanClass == CLASS_STATION) && reason != kOOLegalStatusReasonSetup && reason != kOOLegalStatusReasonByScript)
13601 {
13602 return; // no non-scripted bounties for thargoids and stations
13603 }
13604
13605 JSContext *context = OOJSAcquireContext();
13606
13607 jsval amountVal = JSVAL_VOID;
13608 JS_NewNumberValue(context, (bounty | offence_value)-bounty, &amountVal);
13609
13610 bounty |= offence_value; // can't set the new bounty until the size of the change is known
13611
13612 jsval reasonVal = OOJSValueFromLegalStatusReason(context, reason);
13613
13614 ShipScriptEvent(context, self, "shipBountyChanged", amountVal, reasonVal);
13615
13616 OOJSRelinquishContext(context);
13617
13618 }
13619 }
13620}
OOINLINE jsval OOJSValueFromLegalStatusReason(JSContext *context, OOLegalStatusReason value)
OOLegalStatusReason
Definition OOTypes.h:157
#define ShipScriptEvent(context, ship, event,...)

◆ markedForFines

- (BOOL) markedForFines

Definition at line 14062 of file ShipEntity.m.

14250{
14251 return being_fined;
14252}

◆ markForFines

- (BOOL) markForFines

Definition at line 14062 of file ShipEntity.m.

14256{
14257 if (being_fined)
14258 return NO; // can't mark twice
14259 being_fined = ([self legalStatus] > 0);
14260 return being_fined;
14261}

Referenced by ShipMarkTargetForFines().

+ Here is the caller graph for this function:

◆ markTargetForFines

- (void) markTargetForFines
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2091{
2092 ShipEntity *ship = [self primaryTarget];
2093 if ((ship == nil) || ([ship status] == STATUS_DEAD) || ([ship status] == STATUS_DOCKED))
2094 {
2095 [self noteLostTarget];
2096 return;
2097 }
2098 if ([ship markForFines]) [shipAI message:@"TARGET_MARKED"];
2099}

◆ markTargetForOffence:

- (void) markTargetForOffence: (NSString *)  valueString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2102 :(NSString *)valueString
2103{
2104 if ((isStation)||(scanClass == CLASS_POLICE))
2105 {
2106 ShipEntity *ship = [self primaryTarget];
2107 if ((ship == nil) || ([ship status] == STATUS_DEAD) || ([ship status] == STATUS_DOCKED))
2108 {
2109 [self noteLostTarget];
2110 return;
2111 }
2112 NSString *finalValue = OOExpand(valueString); // expand values
2113 [ship markAsOffender:[finalValue intValue] withReason:kOOLegalStatusReasonSeenByPolice];
2114 }
2115}

◆ maxAftShieldLevel

- (float) maxAftShieldLevel

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

4076{
4077 return BASELINE_SHIELD_LEVEL * [self shieldBoostFactor];
4078}
#define BASELINE_SHIELD_LEVEL
Definition ShipEntity.h:99

◆ maxAvailableCargoSpace

- (OOCargoQuantity) maxAvailableCargoSpace

Definition at line 7616 of file ShipEntity.m.

8366{
8367 return max_cargo - equipment_weight;
8368}

Referenced by OOShipLibraryCargo(), and ShipSetProperty().

+ Here is the caller graph for this function:

◆ maxEscortCount

- (uint8_t) maxEscortCount

Definition at line 6493 of file ShipEntity.m.

7014{
7015 return _maxEscortCount;
7016}

◆ maxFlightPitch

- (GLfloat) maxFlightPitch

Definition at line 7616 of file ShipEntity.m.

8727{
8728 return max_flight_pitch;
8729}

Referenced by OOShipLibraryTurnRate().

+ Here is the caller graph for this function:

◆ maxFlightRoll

- (GLfloat) maxFlightRoll

Definition at line 7616 of file ShipEntity.m.

8739{
8740 return max_flight_roll;
8741}

Referenced by OOShipLibraryTurnRate().

+ Here is the caller graph for this function:

◆ maxFlightSpeed

- (GLfloat) maxFlightSpeed

◆ maxFlightYaw

- (GLfloat) maxFlightYaw

Definition at line 7616 of file ShipEntity.m.

8745{
8746 return max_flight_yaw;
8747}

◆ maxForwardShieldLevel

- (float) maxForwardShieldLevel

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

4070{
4071 return BASELINE_SHIELD_LEVEL * [self shieldBoostFactor];
4072}

◆ maxHyperspaceDistance

- (double) maxHyperspaceDistance

Definition at line 2092 of file ShipEntity.m.

4088{
4089 return MAX_JUMP_RANGE;
4090}
#define MAX_JUMP_RANGE
Definition ShipEntity.h:107

◆ maxShipSubEntities

- (NSUInteger) maxShipSubEntities

Definition at line 14942 of file ShipEntity.m.

793{
794 return _maxShipSubIdx;
795}
NSUInteger _maxShipSubIdx
Definition ShipEntity.h:343

◆ maxThrust

- (float) maxThrust

Definition at line 2092 of file ShipEntity.m.

4117{
4118 return max_thrust;
4119}
GLfloat max_thrust
Definition ShipEntity.h:245

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ mesh

- (OOMesh *) mesh

Definition at line 14942 of file ShipEntity.m.

1249{
1250 return (OOMesh *)[self drawable];
1251}

Referenced by ShipSetMaterialsInternal().

+ Here is the caller graph for this function:

◆ messageMother:

- (void) messageMother: (NSString *)  msgString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1910 :(NSString *)msgString
1911{
1912 ShipEntity *mother = [self owner];
1913 if (mother != nil && mother != self)
1914 {
1915 NSString *context = nil;
1916#ifndef NDEBUG
1917 context = [NSString stringWithFormat:@"%@ messageMother", [self shortDescription]];
1918#endif
1919 [mother reactToAIMessage:msgString context:context];
1920 }
1921}

◆ messageSelf:

- (void) messageSelf: (NSString *)  msgString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1924 :(NSString *)msgString
1925{
1926 [self sendAIMessage:msgString];
1927}

◆ messageTime

- (double) messageTime

◆ missedShots

- (int) missedShots

Definition at line 9589 of file ShipEntity.m.

12079{
12080 if ([self isSubEntity])
12081 {
12082 return [[self owner] missedShots];
12083 }
12084 else
12085 {
12086 return _missed_shots;
12087 }
12088}

◆ missileCapacity

- (NSUInteger) missileCapacity

Definition at line 2092 of file ShipEntity.m.

3933{
3934 return max_missiles;
3935}

Referenced by OOShipLibraryWeapons().

+ Here is the caller graph for this function:

◆ missileCount

- (NSUInteger) missileCount

Definition at line 2092 of file ShipEntity.m.

3927{
3928 return missiles;
3929}

◆ missileLaunchPosition

- (Vector) missileLaunchPosition

Definition at line 9589 of file ShipEntity.m.

12140{
12141 Vector start;
12142 // default launching position
12143 start.x = 0.0f; // in the middle
12144 start.y = boundingBox.min.y - 4.0f; // 4m below bounding box
12145 start.z = boundingBox.max.z + 1.0f; // 1m ahead of bounding box
12146
12147 // custom launching position
12148 start = [shipinfoDictionary oo_vectorForKey:@"missile_launch_position" defaultValue:start];
12149 if (EXPECT_NOT(_scaleFactor != 1.0))
12150 {
12151 start = vector_multiply_scalar(start,_scaleFactor);
12152 }
12153
12154 if (start.x == 0.0f && start.y == 0.0f && start.z <= 0.0f) // The kZeroVector as start is illegal also.
12155 {
12156 OOLog(@"ship.missileLaunch.invalidPosition", @"***** ERROR: The missile_launch_position defines a position %@ behind the %@. In future versions such missiles may explode on launch because they have to travel through the ship.", VectorDescription(start), self);
12157 start.x = 0.0f;
12158 start.y = boundingBox.min.y - 4.0f;
12159 start.z = boundingBox.max.z + 1.0f;
12160 }
12161 return start;
12162}

◆ missileLoadTime

- (OOTimeDelta) missileLoadTime

Definition at line 9589 of file ShipEntity.m.

12323{
12324 return missile_load_time;
12325}

◆ missilesList

- (NSArray *) missilesList

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3302{
3303 // if missile_list is empty, avoid exception and return empty NSArray instead
3304 return missile_list[0] != nil ? [NSArray arrayWithObjects:missile_list count:missiles] :
3305 [NSArray array];
3306}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ missileTrackPrimaryTarget:

- (double) missileTrackPrimaryTarget: (double)  delta_t

Definition at line 9589 of file ShipEntity.m.

10824 :(double) delta_t
10825{
10826 Vector relPos;
10827 GLfloat d_forward, d_up, d_right;
10828 ShipEntity *target = [self primaryTarget];
10829 BOOL inPursuit = YES;
10830
10831 if (!target || ![target isShip]) // leave now!
10832 return 0.0;
10833
10834 double damping = 0.5 * delta_t;
10835
10836 stick_roll = 0.0; //desired roll and pitch
10837 stick_pitch = 0.0;
10838 stick_yaw = 0.0;
10839
10840 relPos = [self vectorTo:target];
10841
10842 // Adjust missile course by taking into account target's velocity and missile
10843 // accuracy. Modification on original code contributed by Cmdr James.
10844
10845 float missileSpeed = (float)[self speed];
10846
10847 // Avoid getting ourselves in a divide by zero situation by setting a missileSpeed
10848 // low threshold. Arbitrarily chosen 0.01, since it seems to work quite well.
10849 // Missile accuracy is already clamped within the 0.0 to 10.0 range at initialization,
10850 // but doing these calculations every frame when accuracy equals 0.0 just wastes cycles.
10851 if (missileSpeed > 0.01f && accuracy > 0.0f)
10852 {
10853 inPursuit = (dot_product([target forwardVector], v_forward) > 0.0f);
10854 if (inPursuit)
10855 {
10856 Vector leading = [target velocity];
10857 float lead = magnitude(relPos) / missileSpeed;
10858
10859 // Adjust where we are going to take into account target's velocity.
10860 // Use accuracy value to determine how well missile will track target.
10861 relPos.x += (lead * leading.x * (accuracy / 10.0f));
10862 relPos.y += (lead * leading.y * (accuracy / 10.0f));
10863 relPos.z += (lead * leading.z * (accuracy / 10.0f));
10864 }
10865 }
10866
10867 if (!vector_equal(relPos, kZeroVector)) relPos = vector_normal(relPos);
10868 else relPos.z = 1.0;
10869
10870 d_right = dot_product(relPos, v_right); // = cosine of angle between angle to target and v_right
10871 d_up = dot_product(relPos, v_up); // = cosine of angle between angle to target and v_up
10872 d_forward = dot_product(relPos, v_forward); // = cosine of angle between angle to target and v_forward
10873
10874 // begin rule-of-thumb manoeuvres
10875
10876 stick_roll = 0.0;
10877
10878 if (pitching_over)
10879 pitching_over = (stick_pitch != 0.0);
10880
10881 if ((d_forward < -pitch_tolerance) && (!pitching_over))
10882 {
10883 pitching_over = YES;
10884 if (d_up >= 0)
10886 if (d_up < 0)
10888 }
10889
10890 if (pitching_over)
10891 {
10892 pitching_over = (d_forward < 0.5);
10893 }
10894 else
10895 {
10896 stick_pitch = -max_flight_pitch * d_up;
10897 stick_roll = -max_flight_roll * d_right;
10898 }
10899
10900 // end rule-of-thumb manoeuvres
10901
10902 // apply damping
10903 if (flightRoll < 0)
10904 flightRoll += (flightRoll < -damping) ? damping : -flightRoll;
10905 if (flightRoll > 0)
10906 flightRoll -= (flightRoll > damping) ? damping : flightRoll;
10907 if (flightPitch < 0)
10908 flightPitch += (flightPitch < -damping) ? damping : -flightPitch;
10909 if (flightPitch > 0)
10910 flightPitch -= (flightPitch > damping) ? damping : flightPitch;
10911
10912
10913 [self applySticks:delta_t];
10914
10915 //
10916 // return target confidence 0.0 .. 1.0
10917 //
10918 if (d_forward < 0.0)
10919 return 0.0;
10920 return d_forward;
10921}
Vector forwardVector()
GLfloat pitch_tolerance
Definition ShipEntity.h:374

◆ name

- (NSString *) name

◆ nextBeacon

- (Entity< OOBeaconEntity > *) nextBeacon
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1632{
1633 return [_nextBeacon weakRefUnderlyingObject];
1634}

◆ noteFrustration:

- (void) noteFrustration: (NSString *)  context
implementation

Provided by category ShipEntity(Private).

Definition at line 2092 of file ShipEntity.m.

2952 :(NSString *)context
2953{
2954 [shipAI reactToMessage:@"FRUSTRATED" context:context];
2955 [self doScriptEvent:OOJSID("shipAIFrustrated") withArgument:context];
2956}

◆ noteKilledBy:damageType:

- (void) noteKilledBy: (Entity *)  whom
damageType: (OOShipDamageType type 

Definition at line 7616 of file ShipEntity.m.

9007 :(Entity *)whom damageType:(OOShipDamageType)type
9008{
9009 if ([self status] == STATUS_DEAD) return;
9010
9011 [PLAYER setScriptTarget:self];
9012
9013 JSContext *context = OOJSAcquireContext();
9014
9015 jsval whomVal = OOJSValueFromNativeObject(context, whom);
9016 jsval typeVal = OOJSValueFromShipDamageType(context, type);
9017 OOEntityStatus originalStatus = [self status];
9018 [self setStatus:STATUS_DEAD];
9019
9020 ShipScriptEvent(context, self, "shipDied", whomVal, typeVal);
9021 if ([whom isShip])
9022 {
9023 jsval selfVal = OOJSValueFromNativeObject(context, self);
9024 ShipScriptEvent(context, (ShipEntity *)whom, "shipKilledOther", selfVal, typeVal);
9025 }
9026
9027 [self setStatus:originalStatus];
9028 OOJSRelinquishContext(context);
9029}
OOINLINE jsval OOJSValueFromShipDamageType(JSContext *context, OOShipDamageType value)

◆ noteLostTarget

- (void) noteLostTarget

Definition at line 9589 of file ShipEntity.m.

10187{
10188 id target = nil;
10189 if ([self primaryTarget] != nil)
10190 {
10191 ShipEntity* ship = [self primaryTarget];
10192 if ([self isDefenseTarget:ship])
10193 {
10194 [self removeDefenseTarget:ship];
10195 }
10196 // for compatibility with 1.76 behaviour of this function, only pass
10197 // the target as a function parameter if the target is still a potential
10198 // valid target (e.g. not scooped, docked, hyperspaced, etc.)
10199 target = (ship && ship->isShip && [self isValidTarget:ship]) ? (id)ship : nil;
10200 if ([self primaryAggressor] == ship)
10201 {
10203 }
10205 }
10206 // always do target lost
10207 [self doScriptEvent:OOJSID("shipTargetLost") withArgument:target];
10208 if (target == nil) [shipAI message:@"TARGET_LOST"]; // stale target? no major urgency.
10209 else [shipAI reactToMessage:@"TARGET_LOST" context:@"flight updates"]; // execute immediately otherwise.
10210}
OOWeakReference * _primaryAggressor
Definition ShipEntity.h:438

◆ noteLostTargetAndGoIdle

- (void) noteLostTargetAndGoIdle

Definition at line 9589 of file ShipEntity.m.

10214{
10215 behaviour = BEHAVIOUR_IDLE;
10216 frustration = 0.0;
10217 [self noteLostTarget];
10218}

◆ noteTakingDamage:from:type:

- (void) noteTakingDamage: (double)  amount
from: (Entity *)  entity
type: (OOShipDamageType type 

Reimplemented in DockEntity.

Definition at line 7616 of file ShipEntity.m.

8972 :(double)amount from:(Entity *)entity type:(OOShipDamageType)type
8973{
8974 if (amount < 0 || (amount == 0 && [[UNIVERSE gameController] isGamePaused])) return;
8975
8976 JSContext *context = OOJSAcquireContext();
8977
8978 jsval amountVal = JSVAL_VOID;
8979 JS_NewNumberValue(context, amount, &amountVal);
8980 jsval entityVal = OOJSValueFromNativeObject(context, entity);
8981 jsval typeVal = OOJSValueFromShipDamageType(context, type);
8982
8983 ShipScriptEvent(context, self, "shipTakingDamage", amountVal, entityVal, typeVal);
8984 OOJSRelinquishContext(context);
8985
8986 if ([entity isShip]) {
8987// ShipEntity* attacker = (ShipEntity *)entity;
8988 if ([self hasHostileTarget] && accuracy >= COMBAT_AI_IS_SMART && (randf()*10.0 < accuracy || desired_speed < 0.5 * maxFlightSpeed) && behaviour != BEHAVIOUR_EVASIVE_ACTION && behaviour != BEHAVIOUR_FLEE_EVASIVE_ACTION && behaviour != BEHAVIOUR_SCRIPTED_ATTACK_AI)
8989 {
8990 if (behaviour == BEHAVIOUR_FLEE_TARGET)
8991 {
8992// jink should be sufficient to avoid being hit most of the time
8993// if not, this will make a sharp turn and then select a new jink position
8994 behaviour = BEHAVIOUR_FLEE_EVASIVE_ACTION;
8995 }
8996 else
8997 {
8998 behaviour = BEHAVIOUR_EVASIVE_ACTION;
8999 }
9000 frustration = 0.0;
9001 }
9002 }
9003
9004}

◆ noteTargetDestroyed:

- (void) noteTargetDestroyed: (ShipEntity *)  target

Definition at line 9589 of file ShipEntity.m.

10220 :(ShipEntity *)target
10221{
10222 [self collectBountyFor:(ShipEntity *)target];
10223 if ([self primaryTarget] == target)
10224 {
10225 [self removeTarget:target];
10226 [self doScriptEvent:OOJSID("shipTargetDestroyed") withArgument:target];
10227 [shipAI message:@"TARGET_DESTROYED"];
10228 }
10229 if ([self isDefenseTarget:target])
10230 {
10231 [self removeDefenseTarget:target];
10232 [shipAI message:@"DEFENSE_TARGET_DESTROYED"];
10233 [self doScriptEvent:OOJSID("defenseTargetDestroyed") withArgument:target];
10234 }
10235}

◆ noticeECM

- (void) noticeECM

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12336{
12337 if (accuracy >= COMBAT_AI_ISNT_AWFUL && missiles > 0 && [[missile_list[0] identifier] isEqualTo:@"EQ_MISSILE"])
12338 {
12339// if we're being ECMd, and our missiles appear to be standard, and we
12340// have some combat sense, wait a bit before firing the next one!
12341 missile_launch_time = [UNIVERSE getTime] + fmax(2.0,missile_load_time); // set minimum launchtime for the next missile.
12342 }
12343}

◆ numberOfScannedShips

- (int) numberOfScannedShips

Definition at line 9589 of file ShipEntity.m.

9907{
9908 return n_scanned_ships;
9909}

◆ octree

- (Octree *) octree

◆ onTarget:withWeapon:

- (BOOL) onTarget: (OOWeaponFacing direction
withWeapon: (OOWeaponType weapon 

Definition at line 9589 of file ShipEntity.m.

11383 :(OOWeaponFacing)direction withWeapon:(OOWeaponType)weapon_type
11384{
11385 // initialize dq to a value that would normally return NO; dq is handled inside the defaultless switch(direction) statement
11386 // and should alaways be recalculated anyway. Initialization here needed to silence compiler warning - Nikos 20120526
11387 GLfloat dq = -1.0f;
11388 GLfloat d2, radius, astq;
11389 Vector rel_pos, urp;
11390 if ([weapon_type isTurretLaser])
11391 {
11392 return YES;
11393 }
11394
11395 Entity *target = [self primaryTarget];
11396 if (target == nil) return NO;
11397 if ([target status] == STATUS_DEAD) return NO;
11398
11399 if (isSunlit && (target->isSunlit == NO) && (randf() < 0.75))
11400 {
11401 return NO; // 3/4 of the time you can't see from a lit place into a darker place
11402 }
11403 radius = target->collision_radius;
11404 rel_pos = HPVectorToVector(HPvector_subtract([self calculateTargetPosition], position));
11405 d2 = magnitude2(rel_pos);
11406 urp = vector_normal_or_zbasis(rel_pos);
11407
11408 switch (direction)
11409 {
11411 dq = +dot_product(urp, v_forward); // cosine of angle between v_forward and unit relative position
11412 break;
11413
11414 case WEAPON_FACING_AFT:
11415 dq = -dot_product(urp, v_forward); // cosine of angle between v_forward and unit relative position
11416 break;
11417
11418 case WEAPON_FACING_PORT:
11419 dq = -dot_product(urp, v_right); // cosine of angle between v_right and unit relative position
11420 break;
11421
11423 dq = +dot_product(urp, v_right); // cosine of angle between v_right and unit relative position
11424 break;
11425
11426 case WEAPON_FACING_NONE:
11427 break;
11428 }
11429
11430 if (dq < 0.0) return NO;
11431
11432 GLfloat aim = [self currentAimTolerance];
11433 if (dq > aim*aim) return YES;
11434
11435 // cosine of 1/3 of half angle subtended by target (mostly they'll
11436 // fire sooner anyway due to currentAimTolerance, but this should
11437 // almost always be a solid hit)
11438 astq = sqrt(1.0 - radius * radius / (d2 * 9));
11439
11440 return (fabs(dq) >= astq);
11441}
HPVector calculateTargetPosition()

◆ oo_jsClassName

- (NSString *) oo_jsClassName
implementation

Reimplemented from Entity.

Reimplemented in DockEntity, PlayerEntity, and StationEntity.

Provided by category ShipEntity(OOJavaScriptExtensions).

Definition at line 1 of file EntityOOJavaScriptExtensions.m.

129{
130 return @"Ship";
131}

◆ orientationChanged

- (void) orientationChanged
implementation

Reimplemented from Entity.

Reimplemented in PlayerEntity.

Definition at line 6493 of file ShipEntity.m.

6785{
6786 [super orientationChanged];
6787
6791}
Vector vector_up_from_quaternion(Quaternion quat)
Vector vector_right_from_quaternion(Quaternion quat)

◆ overrideScriptInfo:

- (void) overrideScriptInfo: (NSDictionary *)  override

Definition at line 14062 of file ShipEntity.m.

14575 :(NSDictionary *)override
14576{
14577 if (scriptInfo == nil) scriptInfo = [override retain];
14578 else if (override != nil)
14579 {
14580 NSMutableDictionary *newInfo = [NSMutableDictionary dictionaryWithDictionary:scriptInfo];
14581 [newInfo addEntriesFromDictionary:override];
14582 [scriptInfo release];
14583 scriptInfo = [newInfo copy];
14584 }
14585}
NSDictionary * scriptInfo
Definition ShipEntity.h:431

◆ parcelCount

- (NSUInteger) parcelCount

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3909{
3910 return 0;
3911}

◆ parcelListForScripting

- (NSArray *) parcelListForScripting

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3316{
3317 return [NSArray array];
3318}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ passengerCapacity

- (NSUInteger) passengerCapacity

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3921{
3922 return 0;
3923}

Referenced by ShipRemoveEquipment().

+ Here is the caller graph for this function:

◆ passengerCount

- (NSUInteger) passengerCount

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3915{
3916 return 0;
3917}

◆ passengerListForScripting

- (NSArray *) passengerListForScripting

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3310{
3311 return [NSArray array];
3312}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ patrolReportIn

- (void) patrolReportIn
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2051{
2052 // Set a report time in the patrolled station to delay a new launch.
2053 ShipEntity *the_station = [[self group] leader];
2054 if(!the_station || ![the_station isStation]) the_station = [UNIVERSE station];
2055 [(StationEntity*)the_station acceptPatrolReportFrom:self];
2056}

◆ pauseAI:

- (void) pauseAI: (NSString *)  intervalString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

848 :(NSString *)intervalString
849{
850 [shipAI setNextThinkTime:[UNIVERSE getTime] + [intervalString doubleValue]];
851}

◆ pendingEscortCount

- (uint8_t) pendingEscortCount

Definition at line 6493 of file ShipEntity.m.

7002{
7003 return _pendingEscortCount;
7004}
uint8_t _pendingEscortCount
Definition ShipEntity.h:469

◆ performAttack

- (void) performAttack

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

377{
378 if (behaviour != BEHAVIOUR_EVASIVE_ACTION)
379 {
380 behaviour = BEHAVIOUR_ATTACK_TARGET;
381 desired_range = 1250 * randf() + 750; // 750 til 2000
382 frustration = 0.0;
383 }
384}

◆ performBuoyTumble

- (void) performBuoyTumble
implementation

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

509{
510 stick_roll = 0.10;
511 stick_pitch = 0.15;
512 behaviour = BEHAVIOUR_TUMBLE;
513 frustration = 0.0;
514}

◆ performCollect

- (void) performCollect

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

388{
389 behaviour = BEHAVIOUR_COLLECT_TARGET;
390 frustration = 0.0;
391}

◆ performEscort

- (void) performEscort

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

395{
396 if(behaviour != BEHAVIOUR_FORMATION_FORM_UP)
397 {
398 behaviour = BEHAVIOUR_FORMATION_FORM_UP;
399 frustration = 0.0; // behavior changed, reset frustration.
400 }
401}

◆ performFaceDestination

- (void) performFaceDestination

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

405{
406 behaviour = BEHAVIOUR_FACE_DESTINATION;
407 frustration = 0.0;
408}

◆ performFlee

- (void) performFlee

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

412{
413 if (behaviour != BEHAVIOUR_FLEE_EVASIVE_ACTION)
414 {
415 behaviour = BEHAVIOUR_FLEE_TARGET;
416 [self setEvasiveJink:400.0];
417 frustration = 0.0;
418 if (accuracy > COMBAT_AI_ISNT_AWFUL)
419 {
420 // alert! they've got us in their sights! react!!
421 if ([self approachAspectToPrimaryTarget] > 0.9995)
422 {
423 behaviour = randf() < 0.15 ? BEHAVIOUR_EVASIVE_ACTION : BEHAVIOUR_FLEE_EVASIVE_ACTION;
424 }
425 }
426 }
427}

◆ performFlyRacepoints

- (void) performFlyRacepoints
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2726{
2727 next_navpoint_index = 0;
2728 desired_range = collision_radius;
2729 behaviour = BEHAVIOUR_FLY_THRU_NAVPOINTS;
2730}

◆ performFlyToRangeFromDestination

- (void) performFlyToRangeFromDestination

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

431{
432 behaviour = BEHAVIOUR_FLY_RANGE_FROM_DESTINATION;
433 frustration = 0.0;
434}

◆ performHold

- (void) performHold

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

438{
439 desired_speed = 0.0;
440 behaviour = BEHAVIOUR_TRACK_TARGET;
441 frustration = 0.0;
442}

◆ performHyperSpaceExit

- (void) performHyperSpaceExit
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1624{
1625 [self performHyperSpaceExitReplace:YES];
1626}

◆ performHyperSpaceExitReplace:

- (BOOL) performHyperSpaceExitReplace: (BOOL)  replace
implementation

Provided by category ShipEntity(OOAIPrivate).

Definition at line 1 of file ShipEntityAI.m.

2751 :(BOOL)replace
2752{
2753 return [self performHyperSpaceExitReplace:replace toSystem:-1];
2754}

◆ performHyperSpaceExitReplace:toSystem:

- (BOOL) performHyperSpaceExitReplace: (BOOL)  replace
toSystem: (OOSystemID systemID 
implementation

Provided by category ShipEntity(OOAIPrivate).

Definition at line 1 of file ShipEntityAI.m.

2757 :(BOOL)replace toSystem:(OOSystemID)systemID
2758{
2759 if(![self hasHyperspaceMotor])
2760 {
2761 [shipAI reactToMessage:@"WITCHSPACE UNAVAILABLE" context:@"performHyperSpaceExit"];
2762 return NO;
2763 }
2764 if([self status] == STATUS_ENTERING_WITCHSPACE)
2765 {
2766// already in a wormhole
2767 return NO;
2768 }
2769
2770 NSArray *sDests = nil;
2771 OOSystemID targetSystem;
2772 NSUInteger i = 0;
2773
2774 // get a list of destinations within range
2775 sDests = [UNIVERSE nearbyDestinationsWithinRange: 0.1f * fuel];
2776 NSUInteger n_dests = [sDests count];
2777
2778 // if none available report to the AI and exit
2779 if (n_dests == 0)
2780 {
2781 [shipAI reactToMessage:@"WITCHSPACE UNAVAILABLE" context:@"performHyperSpaceExit"];
2782
2783 // If no systems exist near us, the AI is switched to a different state, so we do not need
2784 // the nearby destinations array anymore.
2785 return NO;
2786 }
2787
2788 // check if we're clear of nearby masses
2789 ShipEntity *blocker = [UNIVERSE entityForUniversalID:[self checkShipsInVicinityForWitchJumpExit]];
2790 if (blocker)
2791 {
2792 [self setFoundTarget:blocker];
2793 [shipAI reactToMessage:@"WITCHSPACE BLOCKED" context:@"performHyperSpaceExit"];
2794 [self doScriptEvent:OOJSID("shipWitchspaceBlocked") withArgument:blocker];
2795
2796 return NO;
2797 }
2798
2799 if (systemID == -1)
2800 {
2801 // select one at random
2802 if (n_dests > 1)
2803 {
2804 i = ranrot_rand() % n_dests;
2805 }
2806
2807
2808 targetSystem = [[sDests oo_dictionaryAtIndex:i] oo_intForKey:@"sysID"];
2809 }
2810 else
2811 {
2812 targetSystem = systemID;
2813
2814 for (i = 0; i < n_dests; i++)
2815 {
2816 if (systemID == [[sDests oo_dictionaryAtIndex:i] oo_intForKey:@"sysID"]) break;
2817 }
2818
2819 if (i == n_dests) // no match found
2820 {
2821 return NO;
2822 }
2823 }
2824 float dist = [[sDests oo_dictionaryAtIndex:i] oo_floatForKey:@"distance"];
2825 if (dist > [self maxHyperspaceDistance] || dist > fuel/10.0f)
2826 {
2827 OOLogWARN(@"script.debug", @"DEBUG: %@ Jumping %f which is further than allowed. I have %d fuel", self, dist, fuel);
2828 }
2829 fuel -= 10 * dist;
2830
2831 // create wormhole
2832 WormholeEntity *whole = [[[WormholeEntity alloc] initWormholeTo: targetSystem fromShip:self] autorelease];
2833 [UNIVERSE addEntity: whole];
2834
2835 [self enterWormhole:whole replacing:replace];
2836
2837 // we've no need for the destinations array anymore.
2838 return YES;
2839}
#define OOLogWARN(class, format,...)
Definition OOLogging.h:113
int16_t OOSystemID
Definition OOTypes.h:211

◆ performHyperSpaceExitWithoutReplacing

- (void) performHyperSpaceExitWithoutReplacing
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1630{
1631 [self performHyperSpaceExitReplace:NO];
1632}

◆ performHyperSpaceToSpecificSystem:

- (BOOL) performHyperSpaceToSpecificSystem: (OOSystemID systemID

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

534 :(OOSystemID)systemID
535{
536 return [self performHyperSpaceExitReplace:NO toSystem:systemID];
537}

Referenced by ShipExitSystem().

+ Here is the caller graph for this function:

◆ performIdle

- (void) performIdle

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

446{
447 behaviour = BEHAVIOUR_IDLE;
448 frustration = 0.0;
449}

◆ performIntercept

- (void) performIntercept

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

453{
454 behaviour = BEHAVIOUR_INTERCEPT_TARGET;
455 frustration = 0.0;
456}

◆ performLandOnPlanet

- (void) performLandOnPlanet

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

460{
461 OOPlanetEntity *nearest = [self findNearestPlanet];
462 if (isNearPlanetSurface)
463 {
464 _destination = [nearest position];
465 behaviour = BEHAVIOUR_LAND_ON_PLANET;
466 planetForLanding = [nearest universalID];
467 }
468 else
469 {
470 behaviour = BEHAVIOUR_IDLE;
471 [shipAI message:@"NO_PLANET_NEARBY"];
472 }
473
474 frustration = 0.0;
475}

◆ performMining

- (void) performMining

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

479{
480 Entity *target = [self primaryTarget];
481 // mining is not seen as hostile behaviour, so ensure it is only used against rocks.
482 if (target && [target scanClass] == CLASS_ROCK)
483 {
484 behaviour = BEHAVIOUR_ATTACK_MINING_TARGET;
485 frustration = 0.0;
486 }
487 else
488 {
489 [self noteLostTargetAndGoIdle];
490 }
491}

◆ performScriptedAI

- (void) performScriptedAI

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

495{
496 behaviour = BEHAVIOUR_SCRIPTED_AI;
497 frustration = 0.0;
498}

◆ performScriptedAttackAI

- (void) performScriptedAttackAI

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

502{
503 behaviour = BEHAVIOUR_SCRIPTED_ATTACK_AI;
504 frustration = 0.0;
505}

◆ performStop

- (void) performStop

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

518{
519 behaviour = BEHAVIOUR_STOP_STILL;
520 desired_speed = 0.0;
521 frustration = 0.0;
522}

◆ performTumble

- (void) performTumble

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

526{
527 stick_roll = max_flight_roll*2.0*(randf() - 0.5);
528 stick_pitch = max_flight_pitch*2.0*(randf() - 0.5);
529 behaviour = BEHAVIOUR_TUMBLE;
530 frustration = 0.0;
531}

◆ portWeaponOffset

- (NSArray *) portWeaponOffset

◆ positionOffsetForAlignment:

- (Vector) positionOffsetForAlignment: (NSString*)  align

Definition at line 7616 of file ShipEntity.m.

9542 :(NSString*) align
9543{
9544 NSString* padAlign = [NSString stringWithFormat:@"%@---", align];
9545 Vector result = kZeroVector;
9546 switch ([padAlign characterAtIndex:0])
9547 {
9548 case (unichar)'c':
9549 case (unichar)'C':
9550 result.x = 0.5 * (boundingBox.min.x + boundingBox.max.x);
9551 break;
9552 case (unichar)'M':
9553 result.x = boundingBox.max.x;
9554 break;
9555 case (unichar)'m':
9556 result.x = boundingBox.min.x;
9557 break;
9558 }
9559 switch ([padAlign characterAtIndex:1])
9560 {
9561 case (unichar)'c':
9562 case (unichar)'C':
9563 result.y = 0.5 * (boundingBox.min.y + boundingBox.max.y);
9564 break;
9565 case (unichar)'M':
9566 result.y = boundingBox.max.y;
9567 break;
9568 case (unichar)'m':
9569 result.y = boundingBox.min.y;
9570 break;
9571 }
9572 switch ([padAlign characterAtIndex:2])
9573 {
9574 case (unichar)'c':
9575 case (unichar)'C':
9576 result.z = 0.5 * (boundingBox.min.z + boundingBox.max.z);
9577 break;
9578 case (unichar)'M':
9579 result.z = boundingBox.max.z;
9580 break;
9581 case (unichar)'m':
9582 result.z = boundingBox.min.z;
9583 break;
9584 }
9585 return result;
9586}

◆ positionOffsetForShipInRotationToAlignment

- (Vector) positionOffsetForShipInRotationToAlignment (ShipEntity *)  ship
(Quaternion)  q
(NSString *)  align 

Definition at line 9589 of file ShipEntity.m.

9590{
9591 NSString* padAlign = [NSString stringWithFormat:@"%@---", align];
9592 Vector i = vector_right_from_quaternion(q);
9593 Vector j = vector_up_from_quaternion(q);
9594 Vector k = vector_forward_from_quaternion(q);
9595 BoundingBox arbb = [ship findBoundingBoxRelativeToPosition:kZeroHPVector InVectors:i :j :k];
9596 Vector result = kZeroVector;
9597 switch ([padAlign characterAtIndex:0])
9598 {
9599 case (unichar)'c':
9600 case (unichar)'C':
9601 result.x = 0.5 * (arbb.min.x + arbb.max.x);
9602 break;
9603 case (unichar)'M':
9604 result.x = arbb.max.x;
9605 break;
9606 case (unichar)'m':
9607 result.x = arbb.min.x;
9608 break;
9609 }
9610 switch ([padAlign characterAtIndex:1])
9611 {
9612 case (unichar)'c':
9613 case (unichar)'C':
9614 result.y = 0.5 * (arbb.min.y + arbb.max.y);
9615 break;
9616 case (unichar)'M':
9617 result.y = arbb.max.y;
9618 break;
9619 case (unichar)'m':
9620 result.y = arbb.min.y;
9621 break;
9622 }
9623 switch ([padAlign characterAtIndex:2])
9624 {
9625 case (unichar)'c':
9626 case (unichar)'C':
9627 result.z = 0.5 * (arbb.min.z + arbb.max.z);
9628 break;
9629 case (unichar)'M':
9630 result.z = arbb.max.z;
9631 break;
9632 case (unichar)'m':
9633 result.z = arbb.min.z;
9634 break;
9635 }
9636 return result;
9637}
BoundingBox findBoundingBoxRelativeToPosition:InVectors:i:j:(HPVector opv,[InVectors] Vector,[i] Vector,[j] Vector k)

◆ prevBeacon

- (Entity< OOBeaconEntity > *) prevBeacon
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1626{
1627 return [_prevBeacon weakRefUnderlyingObject];
1628}

◆ primaryAggressor

- (Entity *) primaryAggressor

Definition at line 9589 of file ShipEntity.m.

9932{
9933 Entity *result = [_primaryAggressor weakRefUnderlyingObject];
9934 if (result == nil || ![self isValidTarget:result])
9935 {
9937 return nil;
9938 }
9939 return result;
9940}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ primaryRole

- (NSString *) primaryRole

◆ primaryTarget

- (id) primaryTarget

Definition at line 9589 of file ShipEntity.m.

10116{
10117 id result = [_primaryTarget weakRefUnderlyingObject];
10118 if ((result == nil && _primaryTarget != nil)
10119 || ![self isValidTarget:result])
10120 {
10122 return nil;
10123 }
10124 else if (EXPECT_NOT(result == self))
10125 {
10126 /* Added in response to a crash report showing recursion in
10127 [PlayerEntity hasHostileTarget].
10128 -- Ahruman 2009-12-17
10129 */
10131 }
10132 return result;
10133}

Referenced by ShipFireMissile(), and ShipGetProperty().

+ Here is the caller graph for this function:

◆ primaryTargetWithoutValidityCheck

- (id) primaryTargetWithoutValidityCheck

Definition at line 9589 of file ShipEntity.m.

10139{
10140 id result = [_primaryTarget weakRefUnderlyingObject];
10141 if (EXPECT_NOT(result == self))
10142 {
10143 // just in case
10145 return nil;
10146 }
10147 return result;
10148}

◆ processBehaviour:

- (void) processBehaviour: (OOTimeDelta delta_t

Definition at line 2092 of file ShipEntity.m.

2792 :(OOTimeDelta)delta_t
2793{
2794 BOOL applyThrust = YES;
2795 switch (behaviour)
2796 {
2797 case BEHAVIOUR_TUMBLE :
2798 [self behaviour_tumble: delta_t];
2799 break;
2800
2801 case BEHAVIOUR_STOP_STILL :
2802 case BEHAVIOUR_STATION_KEEPING :
2803 [self behaviour_stop_still: delta_t];
2804 break;
2805
2806 case BEHAVIOUR_IDLE :
2807 if ([self isSubEntity])
2808 {
2809 applyThrust = NO;
2810 }
2811 [self behaviour_idle: delta_t];
2812 break;
2813
2814 case BEHAVIOUR_TRACTORED :
2815 [self behaviour_tractored: delta_t];
2816 break;
2817
2818 case BEHAVIOUR_TRACK_TARGET :
2819 [self behaviour_track_target: delta_t];
2820 break;
2821
2822 case BEHAVIOUR_INTERCEPT_TARGET :
2823 case BEHAVIOUR_COLLECT_TARGET :
2824 [self behaviour_intercept_target: delta_t];
2825 break;
2826
2827 case BEHAVIOUR_ATTACK_TARGET :
2828 [self behaviour_attack_target: delta_t];
2829 break;
2830
2831 case BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX :
2832 case BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE :
2833 [self behaviour_fly_to_target_six: delta_t];
2834 break;
2835
2836 case BEHAVIOUR_ATTACK_MINING_TARGET :
2837 [self behaviour_attack_mining_target: delta_t];
2838 break;
2839
2840 case BEHAVIOUR_ATTACK_FLY_TO_TARGET :
2841 [self behaviour_attack_fly_to_target: delta_t];
2842 break;
2843
2844 case BEHAVIOUR_ATTACK_FLY_FROM_TARGET :
2845 [self behaviour_attack_fly_from_target: delta_t];
2846 break;
2847
2848 case BEHAVIOUR_ATTACK_BREAK_OFF_TARGET :
2849 [self behaviour_attack_break_off_target: delta_t];
2850 break;
2851
2852 case BEHAVIOUR_ATTACK_SLOW_DOGFIGHT :
2853 [self behaviour_attack_slow_dogfight: delta_t];
2854 break;
2855
2856 case BEHAVIOUR_RUNNING_DEFENSE :
2857 [self behaviour_running_defense: delta_t];
2858 break;
2859
2860 case BEHAVIOUR_ATTACK_BROADSIDE :
2861 [self behaviour_attack_broadside: delta_t];
2862 break;
2863
2864 case BEHAVIOUR_ATTACK_BROADSIDE_LEFT :
2865 [self behaviour_attack_broadside_left: delta_t];
2866 break;
2867
2868 case BEHAVIOUR_ATTACK_BROADSIDE_RIGHT :
2869 [self behaviour_attack_broadside_right: delta_t];
2870 break;
2871
2872 case BEHAVIOUR_CLOSE_TO_BROADSIDE_RANGE :
2873 [self behaviour_close_to_broadside_range: delta_t];
2874 break;
2875
2876 case BEHAVIOUR_CLOSE_WITH_TARGET :
2877 [self behaviour_close_with_target: delta_t];
2878 break;
2879
2880 case BEHAVIOUR_ATTACK_SNIPER :
2881 [self behaviour_attack_sniper: delta_t];
2882 break;
2883
2884 case BEHAVIOUR_EVASIVE_ACTION :
2885 case BEHAVIOUR_FLEE_EVASIVE_ACTION :
2886 [self behaviour_evasive_action: delta_t];
2887 break;
2888
2889 case BEHAVIOUR_FLEE_TARGET :
2890 [self behaviour_flee_target: delta_t];
2891 break;
2892
2893 case BEHAVIOUR_FLY_RANGE_FROM_DESTINATION :
2894 [self behaviour_fly_range_from_destination: delta_t];
2895 break;
2896
2897 case BEHAVIOUR_FACE_DESTINATION :
2898 [self behaviour_face_destination: delta_t];
2899 break;
2900
2901 case BEHAVIOUR_LAND_ON_PLANET :
2902 [self behaviour_land_on_planet: delta_t];
2903 break;
2904
2905 case BEHAVIOUR_FORMATION_FORM_UP :
2906 [self behaviour_formation_form_up: delta_t];
2907 break;
2908
2909 case BEHAVIOUR_FLY_TO_DESTINATION :
2910 [self behaviour_fly_to_destination: delta_t];
2911 break;
2912
2913 case BEHAVIOUR_FLY_FROM_DESTINATION :
2914 case BEHAVIOUR_FORMATION_BREAK :
2915 [self behaviour_fly_from_destination: delta_t];
2916 break;
2917
2918 case BEHAVIOUR_AVOID_COLLISION :
2919 [self behaviour_avoid_collision: delta_t];
2920 break;
2921
2922 case BEHAVIOUR_TRACK_AS_TURRET :
2923 applyThrust = NO;
2924 [self behaviour_track_as_turret: delta_t];
2925 break;
2926
2927 case BEHAVIOUR_FLY_THRU_NAVPOINTS :
2928 [self behaviour_fly_thru_navpoints: delta_t];
2929 break;
2930
2931 case BEHAVIOUR_SCRIPTED_AI:
2932 case BEHAVIOUR_SCRIPTED_ATTACK_AI:
2933 [self behaviour_scripted_ai: delta_t];
2934 break;
2935
2936 case BEHAVIOUR_ENERGY_BOMB_COUNTDOWN:
2937 applyThrust = NO;
2938 // Do nothing
2939 break;
2940 }
2941
2942 // generally the checks above should be turning this *off* for subents
2943 if (applyThrust)
2944 {
2945 [self applyAttitudeChanges:delta_t];
2946 [self applyThrust:delta_t];
2947 }
2948}
double OOTimeDelta
Definition OOTypes.h:224

◆ proximityAlert

- (Entity *) proximityAlert

Definition at line 6493 of file ShipEntity.m.

7042{
7043 Entity* prox = [_proximityAlert weakRefUnderlyingObject];
7044 if (prox == nil)
7045 {
7047 }
7048 return prox;
7049}
OOWeakReference * _proximityAlert
Definition ShipEntity.h:444

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ randomEjectaTemperature

- (float) randomEjectaTemperature

Definition at line 7616 of file ShipEntity.m.

8794{
8795 return [self randomEjectaTemperatureWithMaxFactor:0.99f];
8796}

◆ randomEjectaTemperatureWithMaxFactor:

- (float) randomEjectaTemperatureWithMaxFactor: (float)  factor

Definition at line 7616 of file ShipEntity.m.

8799 :(float)factor
8800{
8801 const float kRange = 0.02f;
8802 factor -= kRange;
8803
8804 float parentTemp = [self temperature];
8805 float adjusted = parentTemp * (bellf(5) * (kRange * 2.0f) - kRange + factor);
8806 if (adjusted > SHIP_MAX_CABIN_TEMP)
8807 {
8808 adjusted = SHIP_MAX_CABIN_TEMP;
8809 }
8810
8811 // Interpolate so that result == parentTemp when parentTemp is SHIP_MIN_CABIN_TEMP
8812 float interp = OOClamp_0_1_f((parentTemp - SHIP_MIN_CABIN_TEMP) / (SHIP_MAX_CABIN_TEMP - SHIP_MIN_CABIN_TEMP));
8813
8814 return OOLerp(SHIP_MIN_CABIN_TEMP, adjusted, interp);
8815}
float bellf(int n)

◆ randomPauseAI:

- (void) randomPauseAI: (NSString *)  intervalString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

854 :(NSString *)intervalString
855{
856 NSArray* tokens = ScanTokensFromString(intervalString);
857 double start, end;
858
859 if ([tokens count] != 2)
860 {
861 OOLog(@"ai.syntax.randomPauseAI", @"***** ERROR: cannot read min and max value for randomPauseAI:, needs 2 values: '%@'.", intervalString);
862 return;
863 }
864
865 start = [tokens oo_doubleAtIndex:0];
866 end = [tokens oo_doubleAtIndex:1];
867
868 [shipAI setNextThinkTime:[UNIVERSE getTime] + (start + (end - start)*randf())];
869}

◆ randomSeedForShaders

- (uint32_t) randomSeedForShaders
implementation

Definition at line 9589 of file ShipEntity.m.

9774{
9775 return entity_personality * 0x00010001;
9776}

◆ rangeToDestination

- (GLfloat) rangeToDestination

Definition at line 9589 of file ShipEntity.m.

11107{
11108 return HPdistance(position, _destination);
11109}

◆ rangeToPrimaryTarget

- (double) rangeToPrimaryTarget

Definition at line 9589 of file ShipEntity.m.

11232{
11233 return [self rangeToSecondaryTarget:[self primaryTarget]];
11234}

◆ rangeToSecondaryTarget:

- (double) rangeToSecondaryTarget: (Entity *)  target

Definition at line 9589 of file ShipEntity.m.

11237 :(Entity *)target
11238{
11239 double dist;
11240 Vector delta;
11241 if (target == nil) // leave now!
11242 return 0.0;
11243 delta = HPVectorToVector(HPvector_subtract(target->position, position));
11244 dist = magnitude(delta);
11245 dist -= target->collision_radius;
11246 dist -= collision_radius;
11247 return dist;
11248}

◆ rawEscortGroup

- (OOShipGroup *) rawEscortGroup
implementation

Provided by category ShipEntity(Debug).

Definition at line 6493 of file ShipEntity.m.

6955{
6956 return _escortGroup;
6957}

◆ reactionTime

- (float) reactionTime

◆ reactToAIMessage:context:

- (void) reactToAIMessage: (NSString *)  message
context: (NSString *)  debugContext 

Definition at line 14062 of file ShipEntity.m.

14704 :(NSString *)message context:(NSString *)debugContext
14705{
14706 [shipAI reactToMessage:message context:debugContext];
14707}

Referenced by ShipReactToAIMessage().

+ Here is the caller graph for this function:

◆ realAlertCondition

- (OOAlertCondition) realAlertCondition

Reimplemented in PlayerEntity.

Definition at line 14062 of file ShipEntity.m.

14747{
14748 if ([self status] == STATUS_DOCKED)
14749 {
14751 }
14752 if ([self hasHostileTarget])
14753 {
14754 return ALERT_CONDITION_RED;
14755 }
14756 else
14757 {
14758 NSEnumerator *sEnum = [_defenseTargets objectEnumerator];
14759 ShipEntity *ship = nil;
14760 double scanrange2 = scannerRange * scannerRange;
14761 // FIXME: OOWeakSet doesn't implement NSFastEnumeration protocol.
14762 foreach (ship, sEnum)
14763 {
14764 if ([ship hasHostileTarget] || ([ship isPlayer] && [PLAYER weaponsOnline]))
14765 {
14766 if (HPdistance2([ship position],position) < scanrange2)
14767 {
14768 return ALERT_CONDITION_RED;
14769 }
14770 }
14771 }
14772 // also need to check primary target separately
14773 if ([self hasHostileTarget])
14774 {
14775 Entity *ptarget = [self primaryTargetWithoutValidityCheck];
14776 if (ptarget != nil && [ptarget isShip])
14777 {
14778 ship = (ShipEntity *)ptarget;
14779 if ([ship hasHostileTarget] || ([ship isPlayer] && [PLAYER weaponsOnline]))
14780 {
14781 if (HPdistance2([ship position],position) < scanrange2 * 1.5625)
14782 {
14783 return ALERT_CONDITION_RED;
14784 }
14785 }
14786 }
14787 }
14788 if (_group)
14789 {
14790 sEnum = [_group objectEnumerator];
14791 while ((ship = [sEnum nextObject]))
14792 {
14793 if ([ship hasHostileTarget] || ([ship isPlayer] && [PLAYER weaponsOnline]))
14794 {
14795 if (HPdistance2([ship position],position) < scanrange2)
14796 {
14797 return ALERT_CONDITION_RED;
14798 }
14799 }
14800 }
14801 }
14803 {
14804 sEnum = [_escortGroup objectEnumerator];
14805 while ((ship = [sEnum nextObject]))
14806 {
14807 if ([ship hasHostileTarget] || ([ship isPlayer] && [PLAYER weaponsOnline]))
14808 {
14809 if (HPdistance2([ship position],position) < scanrange2)
14810 {
14811 return ALERT_CONDITION_RED;
14812 }
14813 }
14814 }
14815 }
14816 }
14818}

◆ recallDockingInstructions

- (void) recallDockingInstructions

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

598{
599 if (dockingInstructions != nil)
600 {
601 _destination = [dockingInstructions oo_hpvectorForKey:@"destination"];
602 desired_speed = fmin([dockingInstructions oo_floatForKey:@"speed"], maxFlightSpeed);
603 desired_range = [dockingInstructions oo_floatForKey:@"range"];
604 if ([dockingInstructions objectForKey:@"station"])
605 {
606 StationEntity *targetStation = [[dockingInstructions objectForKey:@"station"] weakRefUnderlyingObject];
607 if (targetStation != nil)
608 {
609 [self addTarget:targetStation];
610 [self setTargetStation:targetStation];
611 }
612 else
613 {
614 [self removeTarget:[self primaryTarget]];
615 }
616 }
617 docking_match_rotation = [dockingInstructions oo_boolForKey:@"match_rotation"];
618 }
619}

◆ recallStoredTarget

- (void) recallStoredTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2134{
2135 ShipEntity *oldTarget = (ShipEntity*)[self rememberedShip];
2136 BOOL found = NO;
2137
2138 if (oldTarget && ![oldTarget isCloaked])
2139 {
2140 GLfloat range2 = HPdistance2([oldTarget position], position);
2141 if (range2 <= scannerRange * scannerRange && range2 <= SCANNER_MAX_RANGE2)
2142 {
2143 found = YES;
2144 }
2145 }
2146
2147 if (found)
2148 {
2149 [self setFoundTarget:oldTarget];
2150 [shipAI message:@"TARGET_FOUND"];
2151 }
2152 else
2153 {
2154 if (oldTarget == nil) DESTROY(_rememberedShip); // ship no longer exists
2155 [shipAI message:@"NOTHING_FOUND"];
2156 }
2157
2158}

◆ receiveCommsMessage:from:

- (void) receiveCommsMessage: (NSString *)  message_text
from: (ShipEntity *)  other 

Reimplemented in PlayerEntity.

Definition at line 14062 of file ShipEntity.m.

14227 :(NSString *) message_text from:(ShipEntity *) other
14228{
14229 // Too complex for AI scripts to handle, JS event only.
14230 [self doScriptEvent:OOJSID("commsMessageReceived") withArgument:message_text andArgument:other];
14231}

◆ reference

- (Vector) reference

◆ refreshEscortPositions

- (void) refreshEscortPositions
implementation

Provided by category ShipEntity(Private).

Definition at line 9589 of file ShipEntity.m.

13782{
13784 {
13785 JSContext *context = OOJSAcquireContext();
13786 jsval result;
13787 jsval args[] = { INT_TO_JSVAL(0), INT_TO_JSVAL(_maxEscortCount) };
13788 BOOL OK;
13789
13790 // Reset validity first so updateEscortFormation can be called from the update callback.
13792
13793 uint8_t i;
13794 for (i = 0; i < _maxEscortCount; i++)
13795 {
13796 args[0] = INT_TO_JSVAL(i);
13797 OK = [script callMethod:OOJSID("coordinatesForEscortPosition")
13798 inContext:context
13799 withArguments:args count:sizeof args / sizeof *args
13800 result:&result];
13801
13802 if (OK) OK = JSValueToVector(context, result, &_escortPositions[i]);
13803
13804 if (!OK) _escortPositions[i] = kZeroVector;
13805 }
13806
13807 OOJSRelinquishContext(context);
13808 }
13809}
BOOL JSValueToVector(JSContext *context, jsval value, Vector *outVector) NONNULL_FUNC
Definition OOJSVector.m:259
BOOL _escortPositionsValid
Definition ShipEntity.h:472

◆ releaseCargoPodsDebris

- (void) releaseCargoPodsDebris
implementation

Definition at line 7616 of file ShipEntity.m.

9083{
9084 HPVector xposition = position;
9085 NSUInteger i;
9086 Vector v;
9087 Quaternion q;
9088 int speed_low = 200;
9089
9090 NSArray *jetsam = nil; // this will contain the stuff to get thrown out
9091 unsigned cargo_chance = 70;
9092 jetsam = [NSArray arrayWithArray:cargo]; // what the ship is carrying
9093 [cargo removeAllObjects]; // dispense with it!
9094 unsigned limit = 15;
9095 // Throw out cargo
9096 NSUInteger n_jetsam = [jetsam count];
9097
9098 for (i = 0; i < n_jetsam; i++)
9099 {
9100 if (Ranrot() % 100 < cargo_chance) // chance of any given piece of cargo surviving decompression
9101 {
9102 // a higher chance of getting at least a couple of bits of cargo out
9103 if (cargo_chance > 10)
9104 {
9105 if (EXPECT_NOT([self isPlayer]))
9106 {
9107 cargo_chance -= 20;
9108 }
9109 else
9110 {
9111 cargo_chance -= 30;
9112 }
9113 }
9114 limit--;
9115 ShipEntity* cargoObj = [jetsam objectAtIndex:i];
9116 ShipEntity* container = [UNIVERSE reifyCargoPod:cargoObj];
9117 /* TODO: this debris position/velocity setting code is
9118 * duplicated - sometimes not very cleanly - all over the
9119 * place. Unify to a single function - CIM */
9120 HPVector rpos = xposition;
9122 rpos.x += rrand.x; rpos.y += rrand.y; rpos.z += rrand.z;
9123 rpos.x += (ranrot_rand() % 7) - 3;
9124 rpos.y += (ranrot_rand() % 7) - 3;
9125 rpos.z += (ranrot_rand() % 7) - 3;
9126 [container setPosition:rpos];
9127 v.x = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
9128 v.y = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
9129 v.z = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
9130 [container setVelocity:vector_add(v,[self velocity])];
9132 [container setOrientation:q];
9133
9134 [container setTemperature:[self randomEjectaTemperature]];
9135 [container setScanClass: CLASS_CARGO];
9136 [UNIVERSE addEntity:container]; // STATUS_IN_FLIGHT, AI state GLOBAL
9137
9138 AI *containerAI = [container getAI];
9139 if ([containerAI hasSuspendedStateMachines]) // check if new or recycled cargo.
9140 {
9141 [containerAI exitStateMachineWithMessage:nil];
9142 [container setThrust:[container maxThrust]]; // restore old value. Was set to zero on previous scooping.
9143 [container setOwner:container];
9144 }
9145 }
9146 if (limit <= 0)
9147 {
9148 break; // even really big ships won't have too much cargo survive an explosion
9149 }
9150 }
9151
9152}
void exitStateMachineWithMessage:(NSString *message)
Definition AI.m:296

◆ rememberedShip

- (Entity *) rememberedShip

Definition at line 9589 of file ShipEntity.m.

9989{
9990 Entity *result = [_rememberedShip weakRefUnderlyingObject];
9991 if (result == nil || ![self isValidTarget:result])
9992 {
9994 return nil;
9995 }
9996 return result;
9997}
OOWeakReference * _rememberedShip
Definition ShipEntity.h:443

◆ removeAllDefenseTargets

- (void) removeAllDefenseTargets

Definition at line 9589 of file ShipEntity.m.

11220{
11221 [_defenseTargets removeAllObjects];
11222}

◆ removeAllEquipment

- (void) removeAllEquipment

Definition at line 2092 of file ShipEntity.m.

3895{
3896 [_equipment release];
3897 _equipment = nil;
3898}

◆ removeCargo:amount:

- (BOOL) removeCargo: (OOCommodityType commodity
amount: (OOCargoQuantity amount 

Definition at line 7616 of file ShipEntity.m.

8467 :(OOCommodityType)commodity amount:(OOCargoQuantity) amount
8468{
8469 OOCargoQuantity found = 0;
8470 ShipEntity *pod = nil;
8471 foreach (pod, cargo)
8472 {
8473 if ([[pod commodityType] isEqualToString:commodity])
8474 {
8475 found++;
8476 }
8477 }
8478 if (found < amount)
8479 {
8480 // don't remove any if there aren't enough to remove the full amount
8481 return NO;
8482 }
8483
8484 NSUInteger i = [cargo count] - 1;
8485 // iterate downwards to be safe removing during iteration
8486 while (amount > 0)
8487 {
8488 if ([[[cargo objectAtIndex:i] commodityType] isEqualToString:commodity])
8489 {
8490 amount--;
8491 [cargo removeObjectAtIndex:i];
8492 }
8493 // check above means array index can't underflow here
8494 i--;
8495 }
8496
8497 return YES;
8498}

◆ removeCollisionException:

- (void) removeCollisionException: (ShipEntity *)  ship

Definition at line 9589 of file ShipEntity.m.

11133 :(ShipEntity *)ship
11134{
11136 {
11137 [_collisionExceptions removeObject:ship];
11138 }
11139}

Referenced by ShipRemoveCollisionException().

+ Here is the caller graph for this function:

◆ removeDefenseTarget:

- (void) removeDefenseTarget: (Entity *)  target

Definition at line 9589 of file ShipEntity.m.

11225 :(Entity *)target
11226{
11227 [_defenseTargets removeObject:target];
11228}

◆ removeEquipmentItem:

- (void) removeEquipmentItem: (NSString *)  equipmentKey

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3640 :(NSString *)equipmentKey
3641{
3642 NSString *equipmentTypeCheckKey = equipmentKey;
3643 NSString *lcEquipmentKey = [equipmentKey lowercaseString];
3644 NSUInteger equipmentIndex = NSNotFound;
3645 // determine the equipment type and make sure it works also in the case of damaged equipment
3646 if ([equipmentKey hasSuffix:@"_DAMAGED"])
3647 {
3648 equipmentTypeCheckKey = [equipmentKey substringToIndex:[equipmentKey length] - [@"_DAMAGED" length]];
3649 }
3650 OOEquipmentType *eqType = [OOEquipmentType equipmentTypeWithIdentifier:equipmentTypeCheckKey];
3651 if (eqType == nil) return;
3652
3653 if ([eqType isMissileOrMine] || ([self isThargoid] && ([lcEquipmentKey hasSuffix:@"thargon"] || [lcEquipmentKey hasPrefix:@"thargon"])))
3654 {
3655 [self removeExternalStore:eqType];
3656 }
3657 else
3658 {
3659 if ([_equipment containsObject:equipmentKey])
3660 {
3661 if (![equipmentKey isEqualToString:@"EQ_PASSENGER_BERTH"])
3662 {
3663 equipment_weight -= [eqType requiredCargoSpace]; // all other cases;
3664 }
3665
3666 if ([equipmentKey isEqualToString:@"EQ_CLOAKING_DEVICE"])
3667 {
3668 if ([self isCloaked]) [self setCloaked:NO];
3669 }
3670
3671 if (!isPlayer)
3672 {
3673 if([equipmentKey isEqualToString:@"EQ_SHIELD_BOOSTER"])
3674 {
3675 maxEnergy -= 256.0f;
3677 }
3678 else if([equipmentKey isEqualToString:@"EQ_SHIELD_ENHANCER"])
3679 {
3680 maxEnergy -= 256.0f;
3681 energy_recharge_rate /= 1.5;
3683 }
3684 else if ([equipmentKey isEqual:@"EQ_CARGO_BAY"])
3685 {
3687 }
3688 }
3689 }
3690
3691 if (![equipmentKey hasSuffix:@"_DAMAGED"] && ![eqType canCarryMultiple])
3692 {
3693 NSString *damagedKey = [equipmentKey stringByAppendingString:@"_DAMAGED"];
3694 if ([_equipment containsObject:damagedKey])
3695 {
3696 equipmentIndex = [_equipment indexOfObject:damagedKey];
3697 if (equipmentIndex != NSNotFound)
3698 {
3699 // remove damaged counterpart
3700 [_equipment removeObjectAtIndex:equipmentIndex];
3701 }
3702 equipment_weight -= [eqType requiredCargoSpace];
3703 }
3704 }
3705 equipmentIndex = [_equipment indexOfObject:equipmentKey];
3706 if (equipmentIndex != NSNotFound)
3707 {
3708 [_equipment removeObjectAtIndex:equipmentIndex];
3709 }
3710 // this event must come after the item is actually removed
3711 [self doScriptEvent:OOJSID("equipmentRemoved") withArgument:equipmentKey];
3712
3713 // if all docking computers are damaged while active
3714 if ([self isPlayer] && [self status] == STATUS_AUTOPILOT_ENGAGED && ![self hasDockingComputer])
3715 {
3716 [(PlayerEntity *)self disengageAutopilot];
3717 }
3718
3719
3720 if ([_equipment count] == 0) [self removeAllEquipment];
3721 }
3722}
BOOL hasDockingComputer()

Referenced by ShipRemoveEquipment(), and ShipSetEquipmentStatus().

+ Here is the caller graph for this function:

◆ removeExhaust:

- (void) removeExhaust: (OOExhaustPlumeEntity *)  exhaust

Definition at line 7616 of file ShipEntity.m.

9502 :(OOExhaustPlumeEntity *)exhaust
9503{
9504 [subEntities removeObject:exhaust];
9505 [exhaust setOwner:nil];
9506}

Referenced by OOExhaustPlumeEntity(OOJavaScriptExtensions)::getJSClass:andPrototype:.

+ Here is the caller graph for this function:

◆ removeExternalStore:

- (BOOL) removeExternalStore: (OOEquipmentType *)  eqType

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3725 :(OOEquipmentType *)eqType
3726{
3727 NSString *identifier = [eqType identifier];
3728 unsigned i;
3729
3730 for (i = 0; i < missiles; i++)
3731 {
3732 if ([[missile_list[i] identifier] isEqualTo:identifier])
3733 {
3734 // now 'delete' [i] by compacting the array
3735 while ( ++i < missiles ) missile_list[i - 1] = missile_list[i];
3736
3737 missiles--;
3738 return YES;
3739 }
3740 }
3741 return NO;
3742}

◆ removeFlasher:

- (void) removeFlasher: (OOFlasherEntity *)  flasher

Definition at line 7616 of file ShipEntity.m.

9509 :(OOFlasherEntity *)flasher
9510{
9511 [subEntities removeObject:flasher];
9512 [flasher setOwner:nil];
9513}

◆ removeMissiles

- (OOCreditsQuantity) removeMissiles

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3902{
3903 missiles = 0;
3904 return 0;
3905}

Referenced by ShipAwardEquipment().

+ Here is the caller graph for this function:

◆ removeRole:

- (void) removeRole: (NSString *)  role

Definition at line 6493 of file ShipEntity.m.

7285 :(NSString *)role
7286{
7287 if ([self hasRole:role])
7288 {
7289 OORoleSet *newRoles = [roleSet roleSetWithRemovedRole:role];
7290 if (newRoles != nil)
7291 {
7292 [roleSet release];
7293 roleSet = [newRoles retain];
7294 }
7295 }
7296}

◆ removeScript

- (void) removeScript

Definition at line 14942 of file ShipEntity.m.

1149{
1150 [script autorelease];
1151 script = nil;
1152}

Referenced by ShipRemove().

+ Here is the caller graph for this function:

◆ removeTarget:

- (void) removeTarget: (Entity *)  targetEntity

Definition at line 9589 of file ShipEntity.m.

10067 :(Entity *) targetEntity
10068{
10069 if(targetEntity != nil) [self noteLostTarget];
10070 else DESTROY(_primaryTarget);
10071 // targetEntity == nil is currently only true for mounted player missiles.
10072 // we don't want to send lostTarget messages while the missile is mounted.
10073
10074 [[self shipSubEntityEnumerator] makeObjectsPerformSelector:@selector(removeTarget:) withObject:targetEntity];
10075}

◆ repeatString:times:

- (NSString *) repeatString: (NSString *)  str
times: (NSUInteger)  times 
implementation

Definition at line 14942 of file ShipEntity.m.

798 :(NSString *)str times:(NSUInteger)times
799{
800 if (times == 0) return @"";
801
802 NSMutableString *result = [NSMutableString stringWithCapacity:[str length] * times];
803
804 for (NSUInteger i = 0; i < times; i++)
805 {
806 [result appendString:str];
807 }
808
809 return result;
810}

◆ reportAIMessages

- (BOOL) reportAIMessages

◆ requestDockingCoordinates

- (void) requestDockingCoordinates

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

541{
542 /*- requests coordinates from the target station
543 if the target station can't be found
544 then use the nearest it can find (which may be a rock hermit) -*/
545
546 StationEntity *station = nil;
547 Entity *targStation = nil;
548 NSString *message = nil;
549 double distanceToStation2 = 0.0;
550
551 targStation = [self targetStation];
552 if ([targStation isStation])
553 {
554 station = (StationEntity*)targStation;
555 }
556 else
557 {
558 station = [UNIVERSE nearestShipMatchingPredicate:IsStationPredicate
559 parameter:nil
560 relativeToEntity:self];
561 }
562
563 distanceToStation2 = HPdistance2([station position], [self position]);
564
565 // Player check for being inside the aegis already exists in PlayerEntityControls. We just
566 // check here that distance to station is less than 2.5 times scanner range to avoid problems with
567 // NPC ships getting stuck with a dockingAI while just outside the aegis - Nikos 20090630, as proposed by Eric
568 // On very busy systems (> 50 docking ships) docking ships can be sent to a hold position outside the range,
569 // so also test for presence of dockingInstructions. - Eric 20091130
570 if (station != nil && (distanceToStation2 < SCANNER_MAX_RANGE2 * 6.25 || dockingInstructions != nil))
571 {
572 // remember the instructions
573 [dockingInstructions release];
574 dockingInstructions = [[station dockingInstructionsForShip:self] retain];
575 if (dockingInstructions != nil)
576 {
577 [self recallDockingInstructions];
578
579 message = [dockingInstructions objectForKey:@"ai_message"];
580 if (message != nil) [shipAI message:message];
581 message = [dockingInstructions objectForKey:@"comms_message"];
582 if (message != nil) [station sendExpandedMessage:message toShip:self];
583 }
584 }
585 else
586 {
587 DESTROY(dockingInstructions);
588 }
589
590 if (dockingInstructions == nil)
591 {
592 [shipAI message:@"NO_STATION_FOUND"];
593 }
594}

◆ requestNewTarget

- (void) requestNewTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2227{
2228 ShipEntity *mother = [[self group] leader];
2229 if (mother == nil)
2230 {
2231 [shipAI message:@"MOTHER_LOST"];
2232 return;
2233 }
2234
2235 /*-- Locates all the ships in range targeting the mother ship and chooses the nearest/biggest --*/
2236 DESTROY(_foundTarget);
2237 [self checkScanner];
2238 unsigned i;
2239 GLfloat found_d2 = scannerRange * scannerRange;
2240 GLfloat max_e = 0;
2241 for (i = 0; i < n_scanned_ships ; i++)
2242 {
2243 ShipEntity *thing = scanned_ships[i];
2244 GLfloat d2 = distance2_scanned_ships[i];
2245 GLfloat e1 = [thing energy];
2246 if ((d2 < found_d2) && ![thing isCloaked] && (([thing isThargoid] && ![mother isThargoid]) || (([thing primaryTarget] == mother) && [thing hasHostileTarget])))
2247 {
2248 if (e1 > max_e)
2249 {
2250 [self setFoundTarget:thing];
2251 max_e = e1;
2252 }
2253 }
2254 }
2255
2256 [self checkFoundTarget];
2257}

◆ rescaleBy:

- (void) rescaleBy: (GLfloat)  factor
implementation

Reimplemented from <OOSubEntity>.

Provided by category ShipEntity(Private).

Definition at line 7616 of file ShipEntity.m.

9040 :(GLfloat)factor
9041{
9042 [self rescaleBy:factor writeToCache:YES];
9043}

◆ rescaleBy:writeToCache:

- (void) rescaleBy: (GLfloat)  factor
writeToCache: (BOOL)  writeToCache 
implementation

Reimplemented from <OOSubEntity>.

Provided by category ShipEntity(Private).

Definition at line 7616 of file ShipEntity.m.

9046 :(GLfloat)factor writeToCache:(BOOL)writeToCache
9047{
9048 _scaleFactor *= factor;
9049 OOMesh *mesh = nil;
9050
9051 NSDictionary *shipDict = [self shipInfoDictionary];
9052 NSString *modelName = [shipDict oo_stringForKey:@"model"];
9053 if (modelName != nil)
9054 {
9055 mesh = [OOMesh meshWithName:modelName
9056 cacheKey:[NSString stringWithFormat:@"%@-%.3f",_shipKey,_scaleFactor]
9057 materialDictionary:[shipDict oo_dictionaryForKey:@"materials"]
9058 shadersDictionary:[shipDict oo_dictionaryForKey:@"shaders"]
9059 smooth:[shipDict oo_boolForKey:@"smooth" defaultValue:NO]
9060 shaderMacros:OODefaultShipShaderMacros()
9062 scaleFactor:factor
9063 cacheWriteable:writeToCache];
9064
9065 if (mesh == nil) return;
9066 [self setMesh:mesh];
9067 }
9068
9069 // rescale subentities
9071 foreach (se, [self subEntities])
9072 {
9073 [se setPosition:HPvector_multiply_scalar([se position], factor)];
9074 [se rescaleBy:factor writeToCache:writeToCache];
9075 }
9076
9077 // rescale mass
9078 mass *= factor * factor * factor;
9079}
instancetype meshWithName:cacheKey:materialDictionary:shadersDictionary:smooth:shaderMacros:shaderBindingTarget:scaleFactor:cacheWriteable:(NSString *name,[cacheKey] NSString *cacheKey,[materialDictionary] NSDictionary *materialDict,[shadersDictionary] NSDictionary *shadersDict,[smooth] BOOL smooth,[shaderMacros] NSDictionary *macros,[shaderBindingTarget] id< OOWeakReferenceSupport > object,[scaleFactor] float factor,[cacheWriteable] BOOL cacheWriteable)
Definition OOMesh.m:252
OOMesh * mesh()

◆ resetExhaustPlumes

- (void) resetExhaustPlumes

Definition at line 9589 of file ShipEntity.m.

9796{
9797 OOExhaustPlumeEntity *exEnt = nil;
9798
9799 foreach (exEnt, [self exhaustEnumerator])
9800 {
9801 [exEnt resetPlume];
9802 }
9803}

◆ resetShotTime

- (void) resetShotTime

Definition at line 9589 of file ShipEntity.m.

11632{
11633 shot_time = 0.0;
11634}

◆ respondToAttackFrom:becauseOf:

- (void) respondToAttackFrom: (Entity *)  from
becauseOf: (Entity *)  other 

Definition at line 2092 of file ShipEntity.m.

2959 :(Entity *)from becauseOf:(Entity *)other
2960{
2961 Entity *source = nil;
2962
2963 if ([other isKindOfClass:[ShipEntity class]])
2964 {
2965 source = other;
2966
2967 // JSAIs handle friendly fire themselves
2968 if (![self hasNewAI])
2969 {
2970
2971 ShipEntity *hunter = (ShipEntity *)other;
2972 //if we are in the same group, then we have to be careful about how we handle things
2973 if ([self isPolice] && [hunter isPolice])
2974 {
2975 //police never get into a fight with each other
2976 return;
2977 }
2978
2979 OOShipGroup *group = [self group];
2980
2981 if (group != nil && group == [hunter group])
2982 {
2983 //we are in the same group, do we forgive you?
2984 //criminals are less likely to forgive
2985 if (randf() < (0.8 - (bounty/100)))
2986 {
2987 //it was an honest mistake, lets get on with it
2988 return;
2989 }
2990
2991 ShipEntity *groupLeader = [group leader];
2992 if (hunter == groupLeader)
2993 {
2994 //oops we were attacked by our leader, desert him
2995 [group removeShip:self];
2996 }
2997 else
2998 {
2999 //evict them from our group
3000 [group removeShip:hunter];
3001
3002 [groupLeader setFoundTarget:other];
3003 [groupLeader setPrimaryAggressor:hunter];
3004 [groupLeader respondToAttackFrom:from becauseOf:other];
3005 }
3006 }
3007 }
3008 }
3009 else
3010 {
3011 source = from;
3012 }
3013
3014 [self doScriptEvent:OOJSID("shipBeingAttacked") withArgument:source andReactToAIMessage:@"ATTACKED"];
3015 if ([source isShip]) [(ShipEntity *)source doScriptEvent:OOJSID("shipAttackedOther") withArgument:self];
3016}
void respondToAttackFrom:becauseOf:(Entity *from,[becauseOf] Entity *other)

◆ resumePostProximityAlert

- (void) resumePostProximityAlert

Definition at line 6493 of file ShipEntity.m.

6872{
6873 if (!previousCondition) return;
6874
6875 behaviour = [previousCondition oo_intForKey:@"behaviour"];
6876 [_primaryTarget release];
6877 _primaryTarget = [[previousCondition objectForKey:@"primaryTarget"] weakRetain];
6878 [self startTrackingCurve];
6879 desired_range = [previousCondition oo_floatForKey:@"desired_range"];
6880 desired_speed = [previousCondition oo_floatForKey:@"desired_speed"];
6881 _destination = [previousCondition oo_hpvectorForKey:@"destination"];
6882
6883 [previousCondition release];
6885 frustration = 0.0;
6886
6888
6889 //[shipAI message:@"RESTART_DOCKING"]; // if docking, start over, other AIs will ignore this message
6890}

◆ rightVector

- (Vector) rightVector

Definition at line 14942 of file ShipEntity.m.

1284{
1285 return v_right;
1286}

◆ roleSet

- (OORoleSet *) roleSet

◆ rollD:

- (void) rollD: (NSString *)  die_number
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2260 :(NSString *)die_number
2261{
2262 int die_sides = [die_number intValue];
2263 if (die_sides > 0)
2264 {
2265 int die_roll = 1 + (ranrot_rand() % die_sides);
2266 NSString* result = [NSString stringWithFormat:@"ROLL_%d", die_roll];
2267 [shipAI reactToMessage:result context:@"rollD:"];
2268 }
2269 else
2270 {
2271 OOLog(@"ai.rollD.invalidValue", @"***** ERROR: invalid value supplied to rollD: '%@'.", die_number);
2272 }
2273}

◆ rollToMatchUp:rotating:

- (GLfloat) rollToMatchUp: (Vector)  up_vec
rotating: (GLfloat)  match_roll 

Definition at line 9589 of file ShipEntity.m.

11076 :(Vector)up_vec rotating:(GLfloat)match_roll
11077{
11078 GLfloat cosTheta = dot_product(up_vec, v_up); // == cos of angle between up vectors
11079 GLfloat sinTheta = dot_product(up_vec, v_right);
11080
11081 if (!isPlayer)
11082 {
11083 match_roll = -match_roll; // make necessary corrections for a different viewpoint
11084 sinTheta = -sinTheta;
11085 }
11086
11087 if (cosTheta < 0.0f)
11088 {
11089 cosTheta = -cosTheta;
11090 sinTheta = -sinTheta;
11091 }
11092
11093 if (sinTheta > 0.0f)
11094 {
11095 // increase roll rate
11096 return cosTheta * cosTheta * match_roll + sinTheta * sinTheta * max_flight_roll;
11097 }
11098 else
11099 {
11100 // decrease roll rate
11101 return cosTheta * cosTheta * match_roll - sinTheta * sinTheta * max_flight_roll;
11102 }
11103}

◆ safeScriptActionOnTarget:

- (void) safeScriptActionOnTarget: (NSString *)  action
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2594 :(NSString *)action
2595{
2596 PlayerEntity *player = PLAYER;
2597 ShipEntity *targEnt = [self primaryTarget];
2598 ShipEntity *oldTarget = nil;
2599
2600 if ([targEnt isShip])
2601 {
2602 oldTarget = [player scriptTarget];
2603 [player setScriptTarget:(ShipEntity*)targEnt];
2604 [player runUnsanitizedScriptActions:[NSArray arrayWithObject:action]
2606 withContextName:[NSString stringWithFormat:@"<AI \"%@\" state %@ - safeScriptActionOnTarget:>", [[self getAI] name], [[self getAI] state]]
2607 forTarget:targEnt];
2608 [player setScriptTarget:oldTarget];
2609 }
2610}
void runUnsanitizedScriptActions:allowingAIMethods:withContextName:forTarget:(NSArray *unsanitizedActions,[allowingAIMethods] BOOL allowAIMethods,[withContextName] NSString *contextName,[forTarget] ShipEntity *target)
void setScriptTarget:(ShipEntity *ship)

◆ savedShipDictionaryWithContext:

- (NSDictionary *) savedShipDictionaryWithContext: (NSMutableDictionary *)  context

Provided by category ShipEntity(LoadRestore).

Definition at line 362 of file ShipEntityLoadRestore.m.

79 :(NSMutableDictionary *)context
80{
81 NSMutableDictionary *result = [NSMutableDictionary dictionary];
82 if (context == nil) context = [NSMutableDictionary dictionary];
83
84 [result setObject:_shipKey forKey:KEY_SHIP_KEY];
85
86 NSMutableDictionary *updatedShipInfo = [NSMutableDictionary dictionaryWithDictionary:shipinfoDictionary];
87
88 [updatedShipInfo setObject:[[self roleSet] roleString] forKey:KEY_ROLES];
89 [updatedShipInfo oo_setUnsignedInteger:fuel forKey:KEY_FUEL];
90 [updatedShipInfo oo_setUnsignedLongLong:bounty forKey:KEY_BOUNTY];
91 [updatedShipInfo setObject:OOStringFromWeaponType(forward_weapon_type) forKey:KEY_FORWARD_WEAPON];
92 [updatedShipInfo setObject:OOStringFromWeaponType(aft_weapon_type) forKey:KEY_AFT_WEAPON];
93 [updatedShipInfo setObject:OOStringFromScanClass(scanClass) forKey:KEY_SCAN_CLASS];
94
95 NSArray *deletes = nil;
96 [self simplifyShipdata:updatedShipInfo andGetDeletes:&deletes];
97
98 [result setObject:updatedShipInfo forKey:KEY_SHIPDATA_OVERRIDES];
99 if (deletes != nil) [result setObject:deletes forKey:KEY_SHIPDATA_DELETES];
100
101 if (!HPvector_equal([self position], kZeroHPVector))
102 {
103 [result oo_setHPVector:[self position] forKey:KEY_POSITION];
104 }
105 if (!quaternion_equal([self normalOrientation], kIdentityQuaternion))
106 {
107 [result oo_setQuaternion:[self normalOrientation] forKey:KEY_ORIENTATION];
108 }
109
110 if (energy != maxEnergy) [result oo_setFloat:energy / maxEnergy forKey:KEY_ENERGY_LEVEL];
111
112 [result setObject:[self primaryRole] forKey:KEY_PRIMARY_ROLE];
113
114 // Add equipment.
115 NSArray *equipment = [[self equipmentEnumerator] allObjects];
116 if ([equipment count] != 0) [result setObject:equipment forKey:KEY_EQUIPMENT];
117
118 // Add missiles.
119 if (missiles > 0)
120 {
121 NSMutableArray *missileArray = [NSMutableArray array];
122 unsigned i;
123 for (i = 0; i < missiles; i++)
124 {
125 NSString *missileType = [missile_list[i] identifier];
126 if (missileType != nil) [missileArray addObject:missileType];
127 }
128 [result setObject:missileArray forKey:KEY_MISSILES];
129 }
130
131 // Add groups.
132 if (_group != nil)
133 {
134 [result oo_setUnsignedInteger:GroupIDForGroup(_group, context) forKey:KEY_GROUP_ID];
135 if ([_group leader] == self) [result oo_setBool:YES forKey:KEY_IS_GROUP_LEADER];
136 NSString *groupName = [_group name];
137 if (groupName != nil)
138 {
139 [result setObject:groupName forKey:KEY_GROUP_NAME];
140 }
141 }
142 if (_escortGroup != nil)
143 {
144 [result oo_setUnsignedInteger:GroupIDForGroup(_escortGroup, context) forKey:KEY_ESCORT_GROUP_ID];
145 }
146 /* Eric:
147 The escortGroup property is removed from the lead ship, on entering witchspace.
148 But it is needed in the save file to correctly restore an escorted group.
149 */
150 else if (_group != nil && [_group leader] == self)
151 {
152 [result oo_setUnsignedInteger:GroupIDForGroup(_group, context) forKey:KEY_ESCORT_GROUP_ID];
153 }
154
155 // FIXME: AI.
156 // Eric: I think storing the AI name should be enough. On entering a wormhole, the stack is cleared so there are no preserved AI states.
157 // Also the AI restarts itself with the GLOBAL state, so no need to store any old state.
158 if ([[[self getAI] name] isEqualToString:@"nullAI.plist"])
159 {
160 // might be a JS version
161 [result setObject:[[self getAI] associatedJS] forKey:KEY_AI];
162 // if there isn't, loading nullAI.js will load nullAI.plist anyway
163 }
164 else
165 {
166 [result setObject:[[self getAI] name] forKey:KEY_AI];
167 }
168
169 return result;
170}

◆ scanClass

- (OOScanClass) scanClass
implementation

Reimplemented from Entity.

Definition at line 14942 of file ShipEntity.m.

2063{
2064 if (cloaking_device_active) return CLASS_NO_DRAW;
2065 return scanClass;
2066}

◆ scanDescription

- (NSString *) scanDescription

Definition at line 6493 of file ShipEntity.m.

7163{
7164 if (scan_description != nil)
7165 {
7166 return scan_description;
7167 }
7168 else
7169 {
7170 NSString *desc = nil;
7171 switch ([self scanClass])
7172 {
7173 case CLASS_NEUTRAL:
7174 {
7175 int legal = [self legalStatus];
7176 int legal_i = 0;
7177 if (legal > 0)
7178 {
7179 legal_i = (legal <= 50) ? 1 : 2;
7180 }
7181 desc = [[[UNIVERSE descriptions] oo_arrayForKey:@"legal_status"] oo_stringAtIndex:legal_i];
7182 }
7183 break;
7184
7185 case CLASS_THARGOID:
7186 desc = DESC(@"legal-desc-alien");
7187 break;
7188
7189 case CLASS_POLICE:
7190 desc = DESC(@"legal-desc-system-vessel");
7191 break;
7192
7193 case CLASS_MILITARY:
7194 desc = DESC(@"legal-desc-military-vessel");
7195 break;
7196
7197 default:
7198 break;
7199 }
7200 return desc;
7201 }
7202}

Referenced by HeadUpDisplay::hudDrawReticleOnTarget.

+ Here is the caller graph for this function:

◆ scanDescriptionForScripting

- (NSString *) scanDescriptionForScripting

Definition at line 6493 of file ShipEntity.m.

7157{
7158 return scan_description;
7159}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ scanForFormationLeader

- (void) scanForFormationLeader
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1875{
1876 //-- Locates the nearest suitable formation leader in range --//
1877 DESTROY(_foundTarget);
1878 [self checkScannerIgnoringUnpowered];
1879 unsigned i;
1880 GLfloat found_d2 = scannerRange * scannerRange;
1881 for (i = 0; i < n_scanned_ships; i++)
1882 {
1883 ShipEntity *ship = scanned_ships[i];
1884 if ((ship != self) && (!ship->isPlayer) && (ship->scanClass == scanClass) && [ship primaryTarget] != self && ![ship isCloaked]) // look for alike
1885 {
1886 GLfloat d2 = distance2_scanned_ships[i];
1887 if ((d2 < found_d2) && [ship canAcceptEscort:self])
1888 {
1889 found_d2 = d2;
1890 [self setFoundTarget:ship];
1891 }
1892 }
1893 }
1894
1895 if ([self foundTarget] != nil) [shipAI message:@"TARGET_FOUND"];
1896 else
1897 {
1898 [shipAI message:@"NOTHING_FOUND"];
1899 if ([self hasPrimaryRole:@"wingman"])
1900 {
1901 // become free-lance police :)
1902 [self setAITo:@"route1patrolAI.plist"]; // use this to avoid referencing a released AI
1903 [self setPrimaryRole:@"police"]; // other wingman can now select this ship as leader.
1904 }
1905 }
1906
1907}

◆ scanForHostiles

- (void) scanForHostiles

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

315{
316 /*-- Locates all the ships in range targeting the receiver and chooses the nearest --*/
317 DESTROY(_foundTarget);
318
319 [self checkScanner];
320 unsigned i;
321 GLfloat found_d2 = scannerRange * scannerRange;
322 for (i = 0; i < n_scanned_ships ; i++)
323 {
324 ShipEntity *thing = scanned_ships[i];
325 GLfloat d2 = distance2_scanned_ships[i];
326 if ((d2 < found_d2)
327 && ([thing isThargoid] || (([thing primaryTarget] == self) && [thing hasHostileTarget]) || [thing isDefenseTarget:self])
328 && ![thing isCloaked])
329 {
330 [self setFoundTarget:thing];
331 found_d2 = d2;
332 }
333 }
334
335 [self checkFoundTarget];
336}

◆ scanForLoot

- (void) scanForLoot
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1054{
1055 /*-- Locates the nearest debris in range --*/
1056 if (!isStation)
1057 {
1058 if (![self hasCargoScoop])
1059 {
1060 [shipAI message:@"NOTHING_FOUND"]; //can't collect loot if you have no scoop!
1061 return;
1062 }
1063 if ([cargo count] >= [self maxAvailableCargoSpace])
1064 {
1065 if (max_cargo) [shipAI message:@"HOLD_FULL"]; //can't collect loot if holds are full!
1066 [shipAI message:@"NOTHING_FOUND"]; //can't collect loot if holds are full!
1067 return;
1068 }
1069 }
1070 else
1071 {
1072 if (magnitude2([self velocity]))
1073 {
1074 [shipAI message:@"NOTHING_FOUND"]; //can't collect loot if you're a moving station
1075 return;
1076 }
1077 }
1078
1079 [self checkScanner];
1080
1081 double found_d2 = scannerRange * scannerRange;
1082 DESTROY(_foundTarget);
1083 unsigned i;
1084 for (i = 0; i < n_scanned_ships; i++)
1085 {
1086 ShipEntity *other = (ShipEntity *)scanned_ships[i];
1087 if ([other scanClass] == CLASS_CARGO && [other cargoType] != CARGO_NOT_CARGO && [other status] != STATUS_BEING_SCOOPED)
1088 {
1089 if ((![self isPolice]) || ([[other commodityType] isEqualToString:@"slaves"])) // police only rescue lifepods and slaves
1090 {
1091 GLfloat d2 = distance2_scanned_ships[i];
1092 if (d2 < found_d2)
1093 {
1094 found_d2 = d2;
1095 [self setFoundTarget:other];
1096 }
1097 }
1098 }
1099 }
1100 [self checkFoundTarget];
1101}

◆ scanForNearestIncomingMissile

- (void) scanForNearestIncomingMissile

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

623{
625 {
626 HasScanClassPredicate, [NSNumber numberWithInt:CLASS_MISSILE],
628 };
629 [self scanForNearestShipWithPredicate:ANDPredicate parameter:&param];
630}
BOOL HasScanClassPredicate(Entity *entity, void *parameter)
BOOL IsHostileAgainstTargetPredicate(Entity *ship, void *parameter)

◆ scanForNearestMerchantman

- (void) scanForNearestMerchantman
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

991{
992 float d2, found_d2;
993 unsigned i;
994 ShipEntity *ship = nil;
995
996 //-- Locates the nearest merchantman in range.
997 [self checkScannerIgnoringUnpowered];
998
999 found_d2 = scannerRange * scannerRange;
1000 DESTROY(_foundTarget);
1001
1002 for (i = 0; i < n_scanned_ships ; i++)
1003 {
1004 ship = scanned_ships[i];
1005 if ([ship isPirateVictim] && ([ship status] != STATUS_DEAD) && ([ship status] != STATUS_DOCKED) && ![ship isCloaked])
1006 {
1007 d2 = distance2_scanned_ships[i];
1008 if (PIRATES_PREFER_PLAYER && (d2 < desired_range * desired_range) && ship->isPlayer && [self isPirate])
1009 {
1010 d2 = 0.0;
1011 }
1012 else d2 = distance2_scanned_ships[i];
1013 if (d2 < found_d2)
1014 {
1015 found_d2 = d2;
1016 [self setFoundTarget:ship];
1017 }
1018 }
1019 }
1020 [self checkFoundTarget];
1021}
#define PIRATES_PREFER_PLAYER
Definition ShipEntity.h:40

◆ scanForNearestShipHavingAnyRole:

- (void) scanForNearestShipHavingAnyRole: (NSString *)  scanRoles
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2295 :(NSString *)scanRoles
2296{
2297 NSSet *set = [NSSet setWithArray:ScanTokensFromString(scanRoles)];
2298 [self scanForNearestShipWithPredicate:HasRoleInSetPredicate parameter:set];
2299}

◆ scanForNearestShipHavingRole:

- (void) scanForNearestShipHavingRole: (NSString *)  scanRole
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2282 :(NSString *)scanRole
2283{
2284 [self scanForNearestShipWithPredicate:HasRolePredicate parameter:scanRole];
2285}

◆ scanForNearestShipMatchingPredicate:

- (void) scanForNearestShipMatchingPredicate: (NSString *)  predicateExpression
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2342 :(NSString *)predicateExpression
2343{
2344 /* Takes a boolean-valued JS expression where "ship" is the ship being
2345 evaluated and "this" is our ship's ship script. the expression is
2346 turned into a JS function of the form:
2347
2348 function _oo_AIScanPredicate(ship)
2349 {
2350 return $expression;
2351 }
2352
2353 Examples of expressions:
2354 ship.isWeapon
2355 this.someComplicatedPredicate(ship)
2356 function (ship) { ...do something complicated... } ()
2357 */
2358
2359 static NSMutableDictionary *scriptCache = nil;
2360 NSString *aiName = nil;
2361 NSString *key = nil;
2362 OOJSFunction *function = nil;
2363 JSContext *context = NULL;
2364
2365 context = OOJSAcquireContext();
2366
2367 if (predicateExpression == nil) predicateExpression = @"false";
2368
2369 aiName = [[self getAI] name];
2370#ifndef NDEBUG
2371 /* In debug/test release builds, scripts are cached per AI in order to be
2372 able to report errors correctly. For end-user releases, we only cache
2373 one copy of each predicate, potentially leading to error messages for
2374 the wrong AI.
2375 */
2376 key = [NSString stringWithFormat:@"%@\n%@", aiName, predicateExpression];
2377#else
2378 key = predicateExpression;
2379#endif
2380
2381 // Look for cached function
2382 function = [scriptCache objectForKey:key];
2383 if (function == nil)
2384 {
2385 NSString *predicateCode = nil;
2386 const char *argNames[] = { "ship" };
2387
2388 // Stuff expression in a function.
2389 predicateCode = [NSString stringWithFormat:@"return %@;", predicateExpression];
2390 function = [[OOJSFunction alloc] initWithName:@"_oo_AIScanPredicate"
2391 scope:NULL
2392 code:predicateCode
2393 argumentCount:1
2394 argumentNames:argNames
2395 fileName:aiName
2396 lineNumber:0
2397 context:context];
2398 [function autorelease];
2399
2400 // Cache function.
2401 if (function != nil)
2402 {
2403 if (scriptCache == nil) scriptCache = [[NSMutableDictionary alloc] init];
2404 [scriptCache setObject:function forKey:key];
2405 }
2406 }
2407
2408 if (function != nil)
2409 {
2411 {
2412 .context = context,
2413 .function = [function functionValue],
2414 .jsThis = OOJSObjectFromNativeObject(context, self)
2415 };
2416 [self scanForNearestShipWithPredicate:JSFunctionPredicate parameter:&param];
2417 }
2418 else
2419 {
2420 // Report error (once per occurrence)
2421 static NSMutableSet *errorCache = nil;
2422
2423 if (![errorCache containsObject:key])
2424 {
2425 OOLog(@"ai.scanForNearestShipMatchingPredicate.compile.failed", @"Could not compile JavaScript predicate \"%@\" for AI %@.", predicateExpression, [[self getAI] name]);
2426 if (errorCache == nil) errorCache = [[NSMutableSet alloc] init];
2427 [errorCache addObject:key];
2428 }
2429
2430 // Select nothing
2431 DESTROY(_foundTarget);
2432 [[self getAI] message:@"NOTHING_FOUND"];
2433 }
2434
2435 JS_ReportPendingException(context);
2436 OOJSRelinquishContext(context);
2437}
JSObject * OOJSObjectFromNativeObject(JSContext *context, id object)

◆ scanForNearestShipNotHavingAnyRole:

- (void) scanForNearestShipNotHavingAnyRole: (NSString *)  scanRoles
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2328 :(NSString *)scanRoles
2329{
2330 NSSet *set = [NSSet setWithArray:ScanTokensFromString(scanRoles)];
2331 [self scanForNearestShipWithNegatedPredicate:HasRoleInSetPredicate parameter:set];
2332}

◆ scanForNearestShipNotHavingRole:

- (void) scanForNearestShipNotHavingRole: (NSString *)  scanRole
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2315 :(NSString *)scanRole
2316{
2317 [self scanForNearestShipWithNegatedPredicate:HasRolePredicate parameter:scanRole];
2318}

◆ scanForNearestShipWithAnyPrimaryRole:

- (void) scanForNearestShipWithAnyPrimaryRole: (NSString *)  scanRoles
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2288 :(NSString *)scanRoles
2289{
2290 NSSet *set = [NSSet setWithArray:ScanTokensFromString(scanRoles)];
2291 [self scanForNearestShipWithPredicate:HasPrimaryRoleInSetPredicate parameter:set];
2292}

◆ scanForNearestShipWithNegatedPredicate:parameter:

- (void) scanForNearestShipWithNegatedPredicate: (EntityFilterPredicate predicate
parameter: (void *)  parameter 
implementation

Provided by category ShipEntity(OOAIPrivate).

Definition at line 1 of file ShipEntityAI.m.

2870 :(EntityFilterPredicate)predicate parameter:(void *)parameter
2871{
2872 ChainedEntityPredicateParameter param = { predicate, parameter };
2873 [self scanForNearestShipWithPredicate:NOTPredicate parameter:&param];
2874}
BOOL(* EntityFilterPredicate)(Entity *entity, void *parameter)
Definition Universe.h:52

◆ scanForNearestShipWithoutAnyPrimaryRole:

- (void) scanForNearestShipWithoutAnyPrimaryRole: (NSString *)  scanRoles
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2321 :(NSString *)scanRoles
2322{
2323 NSSet *set = [NSSet setWithArray:ScanTokensFromString(scanRoles)];
2324 [self scanForNearestShipWithNegatedPredicate:HasPrimaryRoleInSetPredicate parameter:set];
2325}

◆ scanForNearestShipWithoutPrimaryRole:

- (void) scanForNearestShipWithoutPrimaryRole: (NSString *)  scanRole
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2309 :(NSString *)scanRole
2310{
2311 [self scanForNearestShipWithNegatedPredicate:HasPrimaryRolePredicate parameter:scanRole];
2312}

◆ scanForNearestShipWithoutScanClass:

- (void) scanForNearestShipWithoutScanClass: (NSString *)  scanScanClass
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2335 :(NSString *)scanScanClass
2336{
2337 NSNumber *parameter = [NSNumber numberWithInt:OOScanClassFromString(scanScanClass)];
2338 [self scanForNearestShipWithNegatedPredicate:HasScanClassPredicate parameter:parameter];
2339}

◆ scanForNearestShipWithPredicate:parameter:

- (void) scanForNearestShipWithPredicate: (EntityFilterPredicate predicate
parameter: (void *)  parameter 
implementation

Provided by category ShipEntity(OOAIPrivate).

Definition at line 1 of file ShipEntityAI.m.

2842 :(EntityFilterPredicate)predicate parameter:(void *)parameter
2843{
2844 // Locates all the ships in range for which predicate returns YES, and chooses the nearest.
2845 unsigned i;
2846 ShipEntity *candidate;
2847 float d2, found_d2 = scannerRange * scannerRange;
2848
2849 DESTROY(_foundTarget);
2850 [self checkScanner];
2851
2852 if (predicate == NULL) return;
2853
2854 for (i = 0; i < n_scanned_ships ; i++)
2855 {
2856 candidate = scanned_ships[i];
2857 d2 = distance2_scanned_ships[i];
2858 if ((d2 < found_d2) && (candidate->scanClass != CLASS_CARGO) && ([candidate status] != STATUS_DOCKED)
2859 && predicate(candidate, parameter) && ![candidate isCloaked])
2860 {
2861 [self setFoundTarget:candidate];
2862 found_d2 = d2;
2863 }
2864 }
2865
2866 [self checkFoundTarget];
2867}

◆ scanForNearestShipWithPrimaryRole:

- (void) scanForNearestShipWithPrimaryRole: (NSString *)  scanRole
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2276 :(NSString *)scanRole
2277{
2278 [self scanForNearestShipWithPredicate:HasPrimaryRolePredicate parameter:scanRole];
2279}

◆ scanForNearestShipWithScanClass:

- (void) scanForNearestShipWithScanClass: (NSString *)  scanScanClass
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2302 :(NSString *)scanScanClass
2303{
2304 NSNumber *parameter = [NSNumber numberWithInt:OOScanClassFromString(scanScanClass)];
2305 [self scanForNearestShipWithPredicate:HasScanClassPredicate parameter:parameter];
2306}

◆ scanForNonThargoid

- (void) scanForNonThargoid
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1692{
1693 /*-- Locates all the non thargoid ships in range and chooses the nearest --*/
1694 DESTROY(_foundTarget);
1695
1696 [self checkScanner];
1697 unsigned i;
1698 GLfloat found_d2 = scannerRange * scannerRange;
1699 for (i = 0; i < n_scanned_ships ; i++)
1700 {
1701 ShipEntity *thing = scanned_ships[i];
1702 GLfloat d2 = distance2_scanned_ships[i];
1703 if (([thing scanClass] != CLASS_CARGO) && ([thing status] != STATUS_DOCKED) && ![thing isThargoid] && ![thing isCloaked] && (d2 < found_d2))
1704 {
1705 [self setFoundTarget:thing];
1706 if ([thing isPlayer]) d2 = 0.0; // prefer the player
1707 found_d2 = d2;
1708 }
1709 }
1710
1711 [self checkFoundTarget];
1712}

◆ scanForOffenders

- (void) scanForOffenders
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1558{
1559 /*-- Locates all the ships in range and compares their legal status or bounty against ranrot_rand() & 255 - chooses the worst offender --*/
1560 NSDictionary *systeminfo = [UNIVERSE currentSystemData];
1561 float gov_factor = 0.4 * [(NSNumber *)[systeminfo objectForKey:KEY_GOVERNMENT] intValue]; // 0 .. 7 (0 anarchic .. 7 most stable) --> [0.0, 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8]
1562 //
1563 if ([UNIVERSE sun] == nil)
1564 gov_factor = 1.0;
1565 //
1566 DESTROY(_foundTarget);
1567
1568 // find the worst offender on the scanner
1569 //
1570 [self checkScanner];
1571 unsigned i;
1572 float worst_legal_factor = 0;
1573 GLfloat found_d2 = scannerRange * scannerRange;
1574 OOShipGroup *group = [self group];
1575 for (i = 0; i < n_scanned_ships ; i++)
1576 {
1577 ShipEntity *ship = scanned_ships[i];
1578 if ((ship->scanClass != CLASS_CARGO)&&([ship status] != STATUS_DEAD)&&([ship status] != STATUS_DOCKED)&& ![ship isCloaked])
1579 {
1580 GLfloat d2 = distance2_scanned_ships[i];
1581 float legal_factor = [ship legalStatus] * gov_factor;
1582 int random_factor = ranrot_rand() & 255; // 25% chance of spotting a fugitive in 15s
1583 if ((d2 < found_d2)&&(random_factor < legal_factor)&&(legal_factor > worst_legal_factor))
1584 {
1585 if (group == nil || group != [ship group]) // fellows with bounty can't be offenders
1586 {
1587 [self setFoundTarget:ship];
1588 worst_legal_factor = legal_factor;
1589 }
1590 }
1591 }
1592 }
1593
1594 [self checkFoundTarget];
1595}

◆ scanForRandomLoot

- (void) scanForRandomLoot
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1105{
1106 /*-- Locates the all debris in range and chooses a piece at random from the first sixteen found --*/
1107 if (![self isStation] && ![self hasCargoScoop])
1108 {
1109 [shipAI message:@"NOTHING_FOUND"]; //can't collect loot if you have no scoop!
1110 return;
1111 }
1112 //
1113 [self checkScanner];
1114 //
1115 ShipEntity* thing_uids_found[16];
1116 unsigned things_found = 0;
1117 DESTROY(_foundTarget);
1118 unsigned i;
1119 for (i = 0; (i < n_scanned_ships)&&(things_found < 16) ; i++)
1120 {
1121 ShipEntity *other = scanned_ships[i];
1122 if ([other scanClass] == CLASS_CARGO && [other cargoType] != CARGO_NOT_CARGO && [other status] != STATUS_BEING_SCOOPED)
1123 {
1124 thing_uids_found[things_found++] = other;
1125 }
1126 }
1127
1128 if (things_found != 0)
1129 {
1130 [self setFoundTarget:thing_uids_found[ranrot_rand() % things_found]];
1131 [shipAI message:@"TARGET_FOUND"];
1132 }
1133 else
1134 [shipAI message:@"NOTHING_FOUND"];
1135}

◆ scanForRandomMerchantman

- (void) scanForRandomMerchantman
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1025{
1026 unsigned n_found, i;
1027
1028 //-- Locates one of the merchantman in range.
1029 [self checkScannerIgnoringUnpowered];
1030 ShipEntity* ids_found[n_scanned_ships];
1031
1032 n_found = 0;
1033 DESTROY(_foundTarget);
1034 for (i = 0; i < n_scanned_ships ; i++)
1035 {
1036 ShipEntity *ship = scanned_ships[i];
1037 if (([ship status] != STATUS_DEAD) && ([ship status] != STATUS_DOCKED) && [ship isPirateVictim] && ![ship isCloaked])
1038 ids_found[n_found++] = ship;
1039 }
1040 if (n_found == 0)
1041 {
1042 [shipAI message:@"NOTHING_FOUND"];
1043 }
1044 else
1045 {
1046 i = ranrot_rand() % n_found; // pick a number from 0 -> (n_found - 1)
1047 [self setFoundTarget:ids_found[i]];
1048 [shipAI message:@"TARGET_FOUND"];
1049 }
1050}

◆ scanForRocks

- (void) scanForRocks
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2161{
2162 /*-- Locates the all boulders and asteroids in range and selects nearest --*/
2163
2164 // find boulders then asteroids within range
2165 //
2166 DESTROY(_foundTarget);
2167 [self checkScanner];
2168 unsigned i;
2169 GLfloat found_d2 = scannerRange * scannerRange;
2170 for (i = 0; i < n_scanned_ships; i++)
2171 {
2172 ShipEntity *thing = scanned_ships[i];
2173 if ([thing isBoulder])
2174 {
2175 GLfloat d2 = distance2_scanned_ships[i];
2176 if (d2 < found_d2)
2177 {
2178 [self setFoundTarget:thing];
2179 found_d2 = d2;
2180 }
2181 }
2182 }
2183 if ([self foundTarget] == nil)
2184 {
2185 for (i = 0; i < n_scanned_ships; i++)
2186 {
2187 ShipEntity *thing = scanned_ships[i];
2188 if ([thing hasRole:@"asteroid"])
2189 {
2190 GLfloat d2 = distance2_scanned_ships[i];
2191 if (d2 < found_d2)
2192 {
2193 [self setFoundTarget:thing];
2194 found_d2 = d2;
2195 }
2196 }
2197 }
2198 }
2199
2200 [self checkFoundTarget];
2201}

◆ scanForThargoid

- (void) scanForThargoid
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1686{
1687 return [self scanForNearestShipWithPrimaryRole:@"thargoid"];
1688}

◆ scannedShips

- (ShipEntity **) scannedShips

Definition at line 9589 of file ShipEntity.m.

9900{
9901 scanned_ships[n_scanned_ships] = nil; // terminate array
9902 return scanned_ships;
9903}

◆ scannerDisplayColor1

- (OOColor *) scannerDisplayColor1

Definition at line 6493 of file ShipEntity.m.

6626{
6627 return [[scanner_display_color1 retain] autorelease];
6628}

Referenced by HeadUpDisplay::hudDrawReticleOnTarget, and ShipGetProperty().

+ Here is the caller graph for this function:

◆ scannerDisplayColor2

- (OOColor *) scannerDisplayColor2

Definition at line 6493 of file ShipEntity.m.

6632{
6633 return [[scanner_display_color2 retain] autorelease];
6634}

Referenced by HeadUpDisplay::hudDrawReticleOnTarget, and ShipGetProperty().

+ Here is the caller graph for this function:

◆ scannerDisplayColorForShip:otherShip:isHostile:flash:scannerDisplayColor1:scannerDisplayColor2:scannerDisplayColorH1:

- (GLfloat *) scannerDisplayColorForShip: (ShipEntity*) 
otherShip: (BOOL) 
isHostile: (BOOL) 
flash: (OOColor *) 
scannerDisplayColor1: (OOColor *) 
scannerDisplayColor2: (OOColor *) 
scannerDisplayColorH1: (OOColor *)  scannerDisplayColorH2 

Definition at line 6493 of file ShipEntity.m.

6495 :(ShipEntity*)otherShip :(BOOL)isHostile :(BOOL)flash :(OOColor *)scannerDisplayColor1 :(OOColor *)scannerDisplayColor2 :(OOColor *)scannerDisplayColorH1 :(OOColor *)scannerDisplayColorH2
6496{
6497 if (isHostile)
6498 {
6499 /* if there are any scripted scanner hostile display colours
6500 * for the ship, use them - otherwise fall through to the
6501 * normal scripted colours, then the scan class colours */
6502 if (scannerDisplayColorH1 || scannerDisplayColorH2)
6503 {
6504 if (scannerDisplayColorH1 && !scannerDisplayColorH2)
6505 {
6506 [scannerDisplayColorH1 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6507 }
6508
6509 if (!scannerDisplayColorH1 && scannerDisplayColorH2)
6510 {
6511 [scannerDisplayColorH2 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6512 }
6513
6514 if (scannerDisplayColorH1 && scannerDisplayColorH2)
6515 {
6516 if (flash)
6517 [scannerDisplayColorH1 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6518 else
6519 [scannerDisplayColorH2 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6520 }
6521
6522 return scripted_color;
6523 }
6524 }
6525
6526 // if there are any scripted scanner display colors for the ship, use them
6528 {
6530 {
6531 [scannerDisplayColor1 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6532 }
6533
6535 {
6536 [scannerDisplayColor2 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6537 }
6538
6540 {
6541 if (flash)
6542 [scannerDisplayColor1 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6543 else
6544 [scannerDisplayColor2 getRed:&scripted_color[0] green:&scripted_color[1] blue:&scripted_color[2] alpha:&scripted_color[3]];
6545 }
6546
6547 return scripted_color;
6548 }
6549
6550 // no scripted scanner display colors defined, proceed as per standard
6551 if ([self isJammingScanning])
6552 {
6553 if (![otherShip hasMilitaryScannerFilter])
6554 return jammed_color;
6555 else
6556 {
6557 if (flash)
6558 return mascem_color1;
6559 else
6560 {
6561 if (isHostile)
6562 return hostile_color;
6563 else
6564 return mascem_color2;
6565 }
6566 }
6567 }
6568
6569 switch (scanClass)
6570 {
6571 case CLASS_ROCK :
6572 case CLASS_CARGO :
6573 return cargo_color;
6574 case CLASS_THARGOID :
6575 if (flash)
6576 return hostile_color;
6577 else
6578 return friendly_color;
6579 case CLASS_MISSILE :
6580 return missile_color;
6581 case CLASS_STATION :
6582 return friendly_color;
6583 case CLASS_BUOY :
6584 if (flash)
6585 return friendly_color;
6586 else
6587 return neutral_color;
6588 case CLASS_POLICE :
6589 case CLASS_MILITARY :
6590 if ((isHostile)&&(flash))
6591 return police_color2;
6592 else
6593 return police_color1;
6594 case CLASS_MINE :
6595 if (flash)
6596 return neutral_color;
6597 else
6598 return hostile_color;
6599 default :
6600 if (isHostile)
6601 return hostile_color;
6602 }
6603 return neutral_color;
6604}
static GLfloat scripted_color[4]
static GLfloat mascem_color1[4]
static GLfloat neutral_color[4]
static GLfloat cargo_color[4]
static GLfloat hostile_color[4]
static GLfloat missile_color[4]
static GLfloat police_color1[4]
static GLfloat mascem_color2[4]
static GLfloat jammed_color[4]
static GLfloat friendly_color[4]
static GLfloat police_color2[4]
void getRed:green:blue:alpha:(float *red,[green] float *green,[blue] float *blue,[alpha] float *alpha)
Definition OOColor.m:368
OOColor * scannerDisplayColor2()
OOColor * scannerDisplayColor1()

◆ scannerDisplayColorHostile1

- (OOColor *) scannerDisplayColorHostile1

Definition at line 6493 of file ShipEntity.m.

6656{
6657 return [[scanner_display_color_hostile1 retain] autorelease];
6658}

Referenced by HeadUpDisplay::hudDrawReticleOnTarget, and ShipGetProperty().

+ Here is the caller graph for this function:

◆ scannerDisplayColorHostile2

- (OOColor *) scannerDisplayColorHostile2

Definition at line 6493 of file ShipEntity.m.

6662{
6663 return [[scanner_display_color_hostile2 retain] autorelease];
6664}

Referenced by HeadUpDisplay::hudDrawReticleOnTarget, and ShipGetProperty().

+ Here is the caller graph for this function:

◆ scannerRange

- (GLfloat) scannerRange

◆ scoopIn:

- (void) scoopIn: (ShipEntity *)  other

Definition at line 9589 of file ShipEntity.m.

12900 :(ShipEntity *)other
12901{
12902 [other getTractoredBy:self];
12903}
void getTractoredBy:(ShipEntity *other)

◆ scoopUp:

- (void) scoopUp: (ShipEntity *)  other

Definition at line 9589 of file ShipEntity.m.

12912 :(ShipEntity *)other
12913{
12914 [self scoopUpProcess:other processEvents:YES processMessages:YES];
12915}

◆ scoopUpProcess:processEvents:processMessages:

- (void) scoopUpProcess: (ShipEntity *)  other
processEvents: (BOOL)  proc_events
processMessages: (BOOL)  proc_messages 

Definition at line 9589 of file ShipEntity.m.

12918 :(ShipEntity *)other processEvents:(BOOL) procEvents processMessages:(BOOL) procMessages
12919{
12920 if (other == nil) return;
12921
12922 OOCommodityType co_type = nil;
12923 OOCargoQuantity co_amount;
12924
12925 // don't even think of trying to scoop if the cargo hold is already full
12926 if (max_cargo && [cargo count] >= [self maxAvailableCargoSpace])
12927 {
12928 [other setStatus:STATUS_IN_FLIGHT];
12929 return;
12930 }
12931
12932 switch ([other cargoType])
12933 {
12934 case CARGO_RANDOM:
12935 co_type = [other commodityType];
12936 co_amount = [other commodityAmount];
12937 break;
12938
12940 {
12941 //scripting
12942 PlayerEntity *player = PLAYER;
12943 [player setScriptTarget:self];
12944 if (procEvents)
12945 {
12946 [other doScriptEvent:OOJSID("shipWasScooped") withArgument:self];
12947 }
12948
12949 if ([other commodityType] != nil)
12950 {
12951 co_type = [other commodityType];
12952 co_amount = [other commodityAmount];
12953 // don't show scoop message now, will happen later.
12954 }
12955 else
12956 {
12957 if (isPlayer && [other showScoopMessage] && procMessages)
12958 {
12959 [UNIVERSE clearPreviousMessage];
12960 NSString *shipName = [other displayName];
12961 [UNIVERSE addMessage:OOExpandKey(@"scripted-item-scooped", shipName) forCount:4];
12962 }
12963 [other setCommodityForPod:nil andAmount:0];
12964 co_amount = 0;
12965 co_type = nil;
12966 }
12967 }
12968 break;
12969
12970 default :
12971 co_amount = 0;
12972 co_type = nil;
12973 break;
12974 }
12975
12976 /* Bug: docking failed due to NSRangeException while looking for element
12977 NSNotFound of cargo mainfest in -[PlayerEntity unloadCargoPods].
12978 Analysis: bad cargo pods being generated due to
12979 -[Universe commodityForName:] looking in wrong place for names.
12980 Fix 1: fix -[Universe commodityForName:].
12981 Fix 2: catch NSNotFound here and substitute random cargo type.
12982 -- Ahruman 20070714
12983 */
12984 if (co_type == nil && co_amount > 0)
12985 {
12986 co_type = [UNIVERSE getRandomCommodity];
12987 co_amount = [UNIVERSE getRandomAmountOfCommodity:co_type];
12988 }
12989
12990 if (co_amount > 0)
12991 {
12992 [other setCommodity:co_type andAmount:co_amount]; // belt and braces setting this!
12994
12995 if (isPlayer)
12996 {
12997 if ([other crew])
12998 {
12999 if ([other showScoopMessage] && procMessages)
13000 {
13001 [UNIVERSE clearPreviousMessage];
13002 unsigned i;
13003 for (i = 0; i < [[other crew] count]; i++)
13004 {
13005 OOCharacter *rescuee = [[other crew] objectAtIndex:i];
13006 NSString *characterName = [rescuee name];
13007 if ([rescuee legalStatus])
13008 {
13009 [UNIVERSE addMessage:OOExpandKey(@"scoop-captured-character", characterName) forCount: 4.5];
13010 }
13011 else if ([rescuee insuranceCredits])
13012 {
13013 [UNIVERSE addMessage:OOExpandKey(@"scoop-rescued-character", characterName) forCount: 4.5];
13014 }
13015 else
13016 {
13017 [UNIVERSE addMessage: DESC(@"scoop-got-slave") forCount: 4.5];
13018 }
13019 }
13020 }
13021 if (procEvents)
13022 {
13023 [(PlayerEntity *)self playEscapePodScooped];
13024 }
13025 }
13026 else
13027 {
13028 if ([other showScoopMessage] && procMessages)
13029 {
13030 [UNIVERSE clearPreviousMessage];
13031 [UNIVERSE addMessage:[UNIVERSE describeCommodity:co_type amount:co_amount] forCount:4.5];
13032 }
13033 }
13034 }
13035 [cargo insertObject:other atIndex:0]; // places most recently scooped object at eject position
13036 [other setStatus:STATUS_IN_HOLD];
13037 [other performTumble];
13038 [shipAI message:@"CARGO_SCOOPED"];
13039 if (max_cargo && [cargo count] >= [self maxAvailableCargoSpace]) [shipAI message:@"HOLD_FULL"];
13040 }
13041 if (procEvents)
13042 {
13043 [self doScriptEvent:OOJSID("shipScoopedOther") withArgument:other]; // always fire, even without commodity.
13044 }
13045
13046 // if shipScoopedOther does something strange to the object, we must
13047 // then remove it from the hold, or it will be over-retained
13048 if ([other status] != STATUS_IN_HOLD)
13049 {
13050 if ([cargo containsObject:other])
13051 {
13052 [cargo removeObject:other];
13053 }
13054 }
13055
13056 [[other collisionArray] removeObject:self]; // so it can't be scooped twice!
13057 // make sure other ships trying to scoop it lose it
13058 // probably already happened, but some may have acquired it
13059 // after the scooping started, and they might get stuck in a scooping
13060 // attempt as a result
13061 [self checkScannerIgnoringUnpowered];
13062 unsigned i;
13063 ShipEntity *scooper;
13064 for (i = 0; i < n_scanned_ships ; i++)
13065 {
13066 scooper = (ShipEntity *)scanned_ships[i];
13067 if (self != scooper && (id) other == [scooper primaryTargetWithoutValidityCheck])
13068 {
13069 [scooper noteLostTarget];
13070 }
13071 }
13072
13073 [self suppressTargetLost];
13074 [UNIVERSE removeEntity:other];
13075}
@ CARGO_RANDOM
Definition OOTypes.h:75
@ CARGO_SCRIPTED_ITEM
Definition OOTypes.h:76
@ CARGO_FLAG_CANISTERS
Definition OOTypes.h:117
NSString * name()
void setStatus:(OOEntityStatus stat)
void performTumble()
void setCommodityForPod:andAmount:(OOCommodityType co_type,[andAmount] OOCargoQuantity co_amount)
BOOL showScoopMessage()

Referenced by ShipAddCargoEntity().

+ Here is the caller graph for this function:

◆ script

- (OOJSScript *) script

◆ scriptActionOnTarget:

- (void) scriptActionOnTarget: (NSString *)  action
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2560 :(NSString *)action
2561{
2562 PlayerEntity *player = PLAYER;
2563 ShipEntity *targEnt = [self primaryTarget];
2564 ShipEntity *oldTarget = nil;
2565
2566#ifndef NDEBUG
2567 static BOOL deprecationWarning = NO;
2568
2569 if (!deprecationWarning)
2570 {
2571 deprecationWarning = YES;
2572 OOLog(@"script.deprecated.scriptActionOnTarget", @"----- WARNING in AI %@: the AI method scriptActionOnTarget: is deprecated and should not be used. It is slow and has unpredictable side effects. The recommended alternative is to use sendScriptMessage: to call a function in a ship's JavaScript ship script instead. scriptActionOnTarget: should not be used at all from scripts. An alternative is safeScriptActionOnTarget:, which is similar to scriptActionOnTarget: but has less side effects.", [AI currentlyRunningAIDescription]);
2573 }
2574 else
2575 {
2576 OOLog(@"script.deprecated.scriptActionOnTarget.repeat", @"----- WARNING in AI %@: the AI method scriptActionOnTarget: is deprecated and should not be used.", [AI currentlyRunningAIDescription]);
2577 }
2578#endif
2579
2580 if ([targEnt isShip])
2581 {
2582 oldTarget = [player scriptTarget];
2583 [player setScriptTarget:(ShipEntity*)targEnt];
2584 [player runUnsanitizedScriptActions:[NSArray arrayWithObject:action]
2586 withContextName:[NSString stringWithFormat:@"<AI \"%@\" state %@ - scriptActionOnTarget:>", [[self getAI] name], [[self getAI] state]]
2587 forTarget:targEnt];
2588 [player checkScript]; // react immediately to any changes this makes
2589 [player setScriptTarget:oldTarget];
2590 }
2591}

◆ scriptedMisjump

- (BOOL) scriptedMisjump

Definition at line 14942 of file ShipEntity.m.

1290{
1291 return scripted_misjump;
1292}
unsigned scripted_misjump
Definition ShipEntity.h:278

◆ scriptedMisjumpRange

- (GLfloat) scriptedMisjumpRange

Definition at line 14942 of file ShipEntity.m.

1302{
1303 return _scriptedMisjumpRange;
1304}
GLfloat _scriptedMisjumpRange
Definition ShipEntity.h:284

◆ scriptInfo

- (NSDictionary *) scriptInfo

◆ selectMissile

- (OOEquipmentType *) selectMissile

Definition at line 2092 of file ShipEntity.m.

3836{
3837 OOEquipmentType *missileType = nil;
3838 NSString *role = nil;
3839 double chance = randf();
3840 BOOL thargoidMissile = NO;
3841
3842 if ([self isThargoid])
3843 {
3844 if (_missileRole != nil) missileType = [self verifiedMissileTypeFromRole:_missileRole];
3845 if (missileType == nil) {
3846 _missileRole = @"EQ_THARGON"; // no valid missile_role defined, use thargoid fallback from now on.
3847 missileType = [self verifiedMissileTypeFromRole:_missileRole];
3848 }
3849 }
3850 else
3851 {
3852 // All other ships: random role 10% of the cases when auto weapons is set, if a missile_role is defined.
3853 // Without auto weapons, never random.
3854 float randomSelectionChance = chance;
3855 if(![self hasAutoWeapons]) randomSelectionChance = 0.0f;
3856 if (randomSelectionChance < 0.9f && _missileRole != nil)
3857 {
3858 missileType = [self verifiedMissileTypeFromRole:_missileRole];
3859 }
3860
3861 if (missileType == nil) // the random 10% , or no valid missile_role defined
3862 {
3863 if (chance < 0.9f && _missileRole != nil) // no valid missile_role defined?
3864 {
3865 _missileRole = nil; // use generic ship fallback from now on.
3866 }
3867
3868 // assign random missiles 20% of the time without missile_role (or 10% with valid missile_role)
3869 if (chance > 0.8f) role = @"missile";
3870 // otherwise use the standard role
3871 else role = @"EQ_MISSILE";
3872
3873 missileType = [self verifiedMissileTypeFromRole:role];
3874 }
3875 }
3876
3877 if (missileType == nil) OOLogERR(@"ship.setUp.missiles", @"could not resolve missile / mine type for ship \"%@\". Original missile role:\"%@\".", [self name],_missileRole);
3878
3879 role = [[missileType identifier] lowercaseString];
3880 thargoidMissile = [self isThargoid] && ([role hasSuffix:@"thargon"] || [role hasPrefix:@"thargon"]);
3881
3882 if (thargoidMissile || (!thargoidMissile && [missileType isMissileOrMine]))
3883 {
3884 return missileType;
3885 }
3886 else
3887 {
3888 OOLogWARN(@"ship.setUp.missiles", @"missile_role \"%@\" is not a valid missile / mine type for ship \"%@\".%@", [missileType identifier] , [self name],@" No missile selected.");
3889 return nil;
3890 }
3891}
BOOL hasAutoWeapons()
NSString * _missileRole
Definition ShipEntity.h:321

Referenced by ShipSelectNewMissile().

+ Here is the caller graph for this function:

◆ sendAIMessage:

- (void) sendAIMessage: (NSString *)  message

Definition at line 14062 of file ShipEntity.m.

14710 :(NSString *)message
14711{
14712 [shipAI message:message];
14713}

Referenced by ShipSendAIMessage().

+ Here is the caller graph for this function:

◆ sendExpandedMessage:toShip:

- (void) sendExpandedMessage: (NSString *)  message_text
toShip: (ShipEntity*)  other_ship 

Definition at line 14062 of file ShipEntity.m.

14138 :(NSString *)message_text toShip:(ShipEntity *)other_ship
14139{
14140 if (!other_ship || !crew)
14141 return; // nobody to receive or send the signal
14142 if ((lastRadioMessage) && (messageTime > 0.0) && [message_text isEqual:lastRadioMessage])
14143 return; // don't send the same message too often
14144 [lastRadioMessage autorelease];
14145 lastRadioMessage = [message_text retain];
14146
14147 double d2 = HPdistance2(position, [other_ship position]);
14148 if (d2 > scannerRange * scannerRange)
14149 {
14150 // out of comms range
14151 return;
14152 }
14153
14154 Random_Seed very_random_seed;
14155 very_random_seed.a = rand() & 255;
14156 very_random_seed.b = rand() & 255;
14157 very_random_seed.c = rand() & 255;
14158 very_random_seed.d = rand() & 255;
14159 very_random_seed.e = rand() & 255;
14160 very_random_seed.f = rand() & 255;
14161 seed_RNG_only_for_planet_description(very_random_seed);
14162
14163 NSDictionary *specials = [NSDictionary dictionaryWithObjectsAndKeys:
14164 [self displayName], @"[self:name]",
14165 [other_ship identFromShip: self], @"[target:name]",
14166 nil];
14167 NSString *expandedMessage = OOExpandDescriptionString(OOStringExpanderDefaultRandomSeed(), message_text, specials, nil, nil, kOOExpandNoOptions);
14168
14169 [self sendMessage:expandedMessage toShip:other_ship withUnpilotedOverride:NO];
14170}
@ kOOExpandNoOptions
Random_Seed OOStringExpanderDefaultRandomSeed(void)
NSString * OOExpandDescriptionString(Random_Seed seed, NSString *string, NSDictionary *overrides, NSDictionary *legacyLocals, NSString *systemName, OOExpandOptions options)
NSString * identFromShip:(ShipEntity *otherShip)

◆ sendMessage:toShip:withUnpilotedOverride:

- (void) sendMessage: (NSString *)  message_text
toShip: (ShipEntity*)  other_ship
withUnpilotedOverride: (BOOL)  unpilotedOverride 

Definition at line 14062 of file ShipEntity.m.

14115 :(NSString *) message_text toShip:(ShipEntity*) other_ship withUnpilotedOverride:(BOOL)unpilotedOverride
14116{
14117 if (!other_ship || !message_text) return;
14118 if (!crew && !unpilotedOverride) return;
14119
14120 double d2 = HPdistance2(position, [other_ship position]);
14121 if (d2 > scannerRange * scannerRange)
14122 return; // out of comms range
14123
14124 NSString *expandedMessage = OOExpand(message_text); // consistent with broadcast message.
14125
14126 if (other_ship->isPlayer)
14127 {
14128 [self setCommsMessageColor];
14129 [(PlayerEntity *)other_ship receiveCommsMessage:expandedMessage from:self];
14130 messageTime = 6.0;
14131 [UNIVERSE resetCommsLogColor];
14132 }
14133 else
14134 [other_ship receiveCommsMessage:expandedMessage from:self];
14135}
void receiveCommsMessage:from:(NSString *message_text,[from] ShipEntity *other)

Referenced by ShipCommsMessage().

+ Here is the caller graph for this function:

◆ sendScriptMessage:

- (void) sendScriptMessage: (NSString *)  message
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2614 :(NSString *)message
2615{
2616 NSArray *components = ScanTokensFromString(message);
2617
2618 if ([components count] == 1)
2619 {
2620 [self doScriptEvent:OOJSIDFromString(message)];
2621 }
2622 else
2623 {
2624 NSString *function = [components objectAtIndex:0];
2625 components = [components subarrayWithRange:NSMakeRange(1, [components count] - 1)];
2626 [self doScriptEvent:OOJSIDFromString(function) withArgument:components];
2627 }
2628}

◆ sendTargetCommsMessage:

- (void) sendTargetCommsMessage: (NSString *)  message
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2078 :(NSString*) message
2079{
2080 ShipEntity *ship = [self primaryTarget];
2081 if ((ship == nil) || ([ship status] == STATUS_DEAD) || ([ship status] == STATUS_DOCKED))
2082 {
2083 [self noteLostTarget];
2084 return;
2085 }
2086 [self sendExpandedMessage:message toShip:[self primaryTarget]];
2087}

◆ serializeShipSubEntities

- (NSString *) serializeShipSubEntities

Definition at line 14942 of file ShipEntity.m.

814{
815 NSMutableString *result = [NSMutableString stringWithCapacity:4];
816 NSEnumerator *subEnum = nil;
817 ShipEntity *se = nil;
818 NSUInteger diff, i = 0;
819
820 for (subEnum = [self shipSubEntityEnumerator]; (se = [subEnum nextObject]); )
821 {
822 diff = [se subIdx] - i;
823 i += diff + 1;
824 [result appendString:[self repeatString:@"0" times:diff]];
825 [result appendString:@"1"];
826 }
827 // add trailing zeroes
828 [result appendString:[self repeatString:@"0" times:[self maxShipSubEntities] - i]];
829 return result;
830}

◆ setAccuracy:

- (void) setAccuracy: (GLfloat)  new_accuracy

Definition at line 14942 of file ShipEntity.m.

1223 :(GLfloat) new_accuracy
1224{
1225 if (new_accuracy < 0.0f && scanClass == CLASS_MISSILE)
1226 {
1227 new_accuracy = 0.0;
1228 }
1229 else if (new_accuracy < -5.0f)
1230 {
1231 new_accuracy = -5.0;
1232 }
1233 else if (new_accuracy > 10.0f)
1234 {
1235 new_accuracy = 10.0;
1236 }
1237 accuracy = new_accuracy;
1238 pitch_tolerance = 0.01 * (85.0f + accuracy);
1239// especially against small targets, less good pilots will waste some shots
1240 aim_tolerance = 240.0 - (18.0f * accuracy);
1241
1243 {
1244 missile_load_time = 2.0; // smart enough not to waste all missiles on 1 ECM!
1245 }
1246}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setAfterburnerFactor:

- (void) setAfterburnerFactor: (GLfloat)  new

Definition at line 2092 of file ShipEntity.m.

4104 :(GLfloat)new
4105{
4107}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setAfterburnerRate:

- (void) setAfterburnerRate: (GLfloat)  new

Definition at line 2092 of file ShipEntity.m.

4110 :(GLfloat)new
4111{
4112 afterburner_rate = new;
4113}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setAI:

- (void) setAI: (AI *)  ai

Definition at line 7616 of file ShipEntity.m.

7999 :(AI *)ai
8000{
8001 [ai retain];
8002 if (shipAI)
8003 {
8004 [shipAI clearAllData];
8005 [shipAI autorelease];
8006 }
8007 shipAI = ai;
8008}

◆ setAIScript:

- (void) setAIScript: (NSString *)  aiString

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

284 :(NSString *)aiString
285{
286 NSMutableDictionary *properties = nil;
287
288 properties = [NSMutableDictionary dictionary];
289 [properties setObject:self forKey:@"ship"];
290
291 [aiScript autorelease];
292 aiScript = [OOScript jsAIScriptFromFileNamed:aiString properties:properties];
293 if (aiScript == nil)
294 {
295 OOLog(@"ai.load.failed.unknownAI",@"Unable to load JS AI %@ for ship %@ (%@ for role %@)",aiString,self,[self shipDataKey],[self primaryRole]);
296 aiScript = [OOScript jsAIScriptFromFileNamed:@"oolite-nullAI.js" properties:properties];
297 }
298 else
299 {
300 aiScriptWakeTime = 0;
301 haveStartedJSAI = NO;
302 }
303 [aiScript retain];
304}
id jsAIScriptFromFileNamed:properties:(NSString *fileName,[properties] NSDictionary *properties)
Definition OOScript.m:220

◆ setAIScriptWakeTime:

- (void) setAIScriptWakeTime: (OOTimeAbsolute t

Definition at line 14942 of file ShipEntity.m.

1414 :(OOTimeAbsolute) t
1415{
1416 aiScriptWakeTime = t;
1417}
double OOTimeAbsolute
Definition OOTypes.h:223

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setAITo:

- (void) setAITo: (NSString *)  aiString

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

252 :(NSString *)aiString
253{
254 // don't try to load real AIs if the game hasn't started yet
255 if (![PLAYER scriptsLoaded])
256 {
257 aiString = @"oolite-nullAI.js";
258 }
259 if ([aiString hasSuffix:@".plist"])
260 {
261 [[self getAI] setStateMachine:aiString withJSScript:@"oolite-nullAI.js"];
262 [self setAIScript:@"oolite-nullAI.js"];
263 }
264 else if ([aiString hasSuffix:@".js"])
265 {
266 [[self getAI] setStateMachine:@"nullAI.plist" withJSScript:aiString];
267 [self setAIScript:aiString];
268 }
269 else
270 {
271 NSString *path = [ResourceManager pathForFileNamed:[aiString stringByAppendingString:@".js"] inFolder:@"AIs"];
272 if (path == nil) // no js, use plist
273 {
274 [self setAITo:[aiString stringByAppendingString:@".plist"]];
275 }
276 else
277 {
278 [self setAITo:[aiString stringByAppendingString:@".js"]];
279 }
280 }
281}
NSString * pathForFileNamed:inFolder:(NSString *fileName,[inFolder] NSString *folderName)

Referenced by ShipSetAI().

+ Here is the caller graph for this function:

◆ setAutoCloak:

- (void) setAutoCloak: (BOOL)  automatic

Definition at line 6493 of file ShipEntity.m.

6692 :(BOOL)automatic
6693{
6694 cloakAutomatic = !!automatic;
6695}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setBeaconCode:

- (void) setBeaconCode: (NSString *)  bcode
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1552 :(NSString *)bcode
1553{
1554 if ([bcode length] == 0) bcode = nil;
1555
1556 if (_beaconCode != bcode)
1557 {
1558 [_beaconCode release];
1559 _beaconCode = [bcode copy];
1560
1562 }
1563 // if not blanking code and label is currently blank, default label to code
1564 if (bcode != nil && (_beaconLabel == nil || [_beaconLabel length] == 0))
1565 {
1566 [self setBeaconLabel:bcode];
1567 }
1568}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setBeaconLabel:

- (void) setBeaconLabel: (NSString *)  blabel
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1577 :(NSString *)blabel
1578{
1579 if ([blabel length] == 0) blabel = nil;
1580
1581 if (_beaconLabel != blabel)
1582 {
1583 [_beaconLabel release];
1584 _beaconLabel = [OOExpand(blabel) retain];
1585 }
1586}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setBehaviour:

- (void) setBehaviour: (OOBehaviour cond

Definition at line 9589 of file ShipEntity.m.

10244 :(OOBehaviour) cond
10245{
10246 if (cond != behaviour)
10247 {
10248 frustration = 0.0; // change is a GOOD thing
10249 behaviour = cond;
10250 }
10251}
OOBehaviour
Definition ShipEntity.h:150

◆ setBounty:

- (void) setBounty: (OOCreditsQuantity amount

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8243 :(OOCreditsQuantity) amount
8244{
8245 [self setBounty:amount withReason:kOOLegalStatusReasonUnknown];
8246}
uint64_t OOCreditsQuantity
Definition OOTypes.h:182

◆ setBounty:withReason:

- (void) setBounty: (OOCreditsQuantity amount
withReason: (OOLegalStatusReason reason 

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8249 :(OOCreditsQuantity) amount withReason:(OOLegalStatusReason)reason
8250{
8251 if ([self isSubEntity])
8252 {
8253 [[self parentEntity] setBounty:amount withReason:reason];
8254 }
8255 else
8256 {
8257 if ((scanClass == CLASS_THARGOID || scanClass == CLASS_STATION) && reason != kOOLegalStatusReasonSetup && reason != kOOLegalStatusReasonByScript)
8258 {
8259 return; // no standard bounties for Thargoids / Stations
8260 }
8261 if (scanClass == CLASS_POLICE && amount != 0)
8262 {
8263 return; // police never have bounties
8264 }
8265 NSString* nReason = OOStringFromLegalStatusReason(reason);
8266 [self setBounty:amount withReasonAsString:nReason];
8267 }
8268}
NSString * OOStringFromLegalStatusReason(OOLegalStatusReason reason)

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setBounty:withReasonAsString:

- (void) setBounty: (OOCreditsQuantity amount
withReasonAsString: (NSString *)  reason 

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8270 :(OOCreditsQuantity) amount withReasonAsString:(NSString*)reason
8271{
8272 if ([self isSubEntity])
8273 {
8274 [[self parentEntity] setBounty:amount withReasonAsString:reason];
8275 }
8276 else
8277 {
8278 JSContext *context = OOJSAcquireContext();
8279
8280 jsval amountVal = JSVAL_VOID;
8281 JS_NewNumberValue(context, (int)amount-(int)bounty, &amountVal);
8282
8283 bounty = amount; // can't set the new bounty until the size of the change is known
8284
8285 jsval reasonVal = OOJSValueFromNativeObject(context,reason);
8286
8287 ShipScriptEvent(context, self, "shipBountyChanged", amountVal, reasonVal);
8288
8289 OOJSRelinquishContext(context);
8290
8291 }
8292}

Referenced by ShipSetBounty().

+ Here is the caller graph for this function:

◆ setCargo:

- (void) setCargo: (NSArray *)  some_cargo

Definition at line 7616 of file ShipEntity.m.

8446 :(NSArray *) some_cargo
8447{
8448 [cargo removeAllObjects];
8449 [cargo addObjectsFromArray:some_cargo];
8450}

◆ setCargoFlag:

- (void) setCargoFlag: (OOCargoFlag flag

Definition at line 7616 of file ShipEntity.m.

8514 :(OOCargoFlag) flag
8515{
8516 if (cargo_flag != flag)
8517 {
8518 cargo_flag = flag;
8519 NSArray *newCargo = nil;
8520 unsigned num = 0;
8521 if (likely_cargo > 0)
8522 {
8523 num = likely_cargo * (0.5+randf());
8524 if (num > [self maxAvailableCargoSpace])
8525 {
8526 num = [self maxAvailableCargoSpace];
8527 }
8528 }
8529 else
8530 {
8531 num = [self maxAvailableCargoSpace];
8532 }
8533 if (num > 200)
8534 {
8535 num = 200;
8536 /* no core NPC ship carries this much when generated (the
8537 * Anaconda could, but doesn't): let's not waste time generating
8538 * thousands of pods - even if they are semi-virtual - for some
8539 * massive OXP ship */
8540 }
8541 if (num > 0)
8542 {
8543 switch (cargo_flag)
8544 {
8546 newCargo = [UNIVERSE getContainersOfCommodity:[shipinfoDictionary oo_stringForKey:@"cargo_carried"] :num];
8547 break;
8549 newCargo = [UNIVERSE getContainersOfGoods:num scarce:NO legal:YES];
8550 break;
8552 newCargo = [UNIVERSE getContainersOfGoods:num scarce:YES legal:YES];
8553 break;
8555 newCargo = [UNIVERSE getContainersOfCommodity:@"Narcotics" :num];
8556 break;
8558 newCargo = [UNIVERSE getContainersOfGoods:num scarce:YES legal:NO];
8559 break;
8560 case CARGO_FLAG_PIRATE:
8561 newCargo = [UNIVERSE getContainersOfGoods:(Ranrot() % (1+num/2)) scarce:YES legal:NO];
8562 break;
8564 // TODO: allow passengers to survive
8565 case CARGO_FLAG_NONE:
8566 default:
8567 break;
8568 }
8569 }
8570 [self setCargo:newCargo];
8571 }
8572}
OOCargoFlag
Definition OOTypes.h:109
@ CARGO_FLAG_FULL_CONTRABAND
Definition OOTypes.h:114
@ CARGO_FLAG_FULL_SCARCE
Definition OOTypes.h:112
@ CARGO_FLAG_FULL_PLENTIFUL
Definition OOTypes.h:111
@ CARGO_FLAG_PIRATE
Definition OOTypes.h:115
@ CARGO_FLAG_FULL_UNIFORM
Definition OOTypes.h:116
@ CARGO_FLAG_FULL_MEDICAL
Definition OOTypes.h:113
@ CARGO_FLAG_FULL_PASSENGERS
Definition OOTypes.h:118
@ CARGO_FLAG_NONE
Definition OOTypes.h:110

Referenced by ShipSetCargoType().

+ Here is the caller graph for this function:

◆ setCloaked:

- (void) setCloaked: (BOOL)  cloak

Definition at line 6493 of file ShipEntity.m.

6679 :(BOOL)cloak
6680{
6681 if (cloak) [self activateCloakingDevice];
6682 else [self deactivateCloakingDevice];
6683}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setCommodity:andAmount:

- (void) setCommodity: (OOCommodityType co_type
andAmount: (OOCargoQuantity co_amount 

Definition at line 7616 of file ShipEntity.m.

8319 :(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount
8320{
8321 if (co_type != nil)
8322 {
8323 /* The tmp variable is needed as scoopUp can cause the method
8324 * to be passed a reference to self.commodity_type, so DESTROY
8325 * then copying the parameter segfaults */
8326 NSString *tmp = [co_type copy];
8328 commodity_type = tmp;
8329 commodity_amount = co_amount;
8330 }
8331}

◆ setCommodityForPod:andAmount:

- (void) setCommodityForPod: (OOCommodityType co_type
andAmount: (OOCargoQuantity co_amount 

Definition at line 7616 of file ShipEntity.m.

8334 :(OOCommodityType)co_type andAmount:(OOCargoQuantity)co_amount
8335{
8336 // can be nil for pods
8337 if (co_type == nil)
8338 {
8340 commodity_amount = 0;
8341 return;
8342 }
8343 // pod content should never be greater than 1 ton or this will give cargo counting problems elsewhere in the code.
8344 // so do first a mass check for cargo added by script/plist.
8345 OOMassUnit unit = [[UNIVERSE commodityMarket] massUnitForGood:co_type];
8346 if (unit == UNITS_TONS && co_amount > 1) co_amount = 1;
8347 else if (unit == UNITS_KILOGRAMS && co_amount > 1000) co_amount = 1000;
8348 else if (unit == UNITS_GRAMS && co_amount > 1000000) co_amount = 1000000;
8349 [self setCommodity:co_type andAmount:co_amount];
8350}
OOMassUnit
Definition OOTypes.h:123
@ UNITS_TONS
Definition OOTypes.h:124
@ UNITS_GRAMS
Definition OOTypes.h:126
@ UNITS_KILOGRAMS
Definition OOTypes.h:125

Referenced by ShipSetCargo().

+ Here is the caller graph for this function:

◆ setCommsMessageColor

- (void) setCommsMessageColor

Definition at line 14062 of file ShipEntity.m.

14217{
14218 float hue = 0.0625f * (universalID & 15);
14219 [[UNIVERSE commLogGUI] setTextColor:[OOColor colorWithHue:hue saturation:0.375f brightness:1.0f alpha:1.0f]];
14220 if (scanClass == CLASS_THARGOID)
14221 [[UNIVERSE commLogGUI] setTextColor:[OOColor greenColor]];
14222 if (scanClass == CLASS_POLICE)
14223 [[UNIVERSE commLogGUI] setTextColor:[OOColor cyanColor]];
14224}
OOColor * cyanColor()
Definition OOColor.m:286
OOColor * greenColor()
Definition OOColor.m:274
OOColor * colorWithHue:saturation:brightness:alpha:(float hue,[saturation] float saturation,[brightness] float brightness,[alpha] float alpha)
Definition OOColor.m:87

◆ setCoordinate:

- (void) setCoordinate: (HPVector)  coord

Definition at line 9589 of file ShipEntity.m.

10264 :(HPVector) coord // The name "setCoordinates" is already used by AI scripting.
10265{
10266 coordinates = coord;
10267}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setCoordinates:

- (void) setCoordinates: (NSString *)  system_x_y_z
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2440 :(NSString *)system_x_y_z
2441{
2442 NSArray* tokens = ScanTokensFromString(system_x_y_z);
2443 NSString* systemString = nil;
2444 NSString* xString = nil;
2445 NSString* yString = nil;
2446 NSString* zString = nil;
2447
2448 if ([tokens count] != 4)
2449 {
2450 OOLog(@"ai.syntax.setCoordinates", @"***** ERROR: cannot setCoordinates: '%@'.",system_x_y_z);
2451 return;
2452 }
2453
2454 systemString = (NSString *)[tokens objectAtIndex:0];
2455 xString = (NSString *)[tokens objectAtIndex:1];
2456 if ([xString hasPrefix:@"rand:"])
2457 xString = [NSString stringWithFormat:@"%.3f", bellf([(NSString*)[[xString componentsSeparatedByString:@":"] objectAtIndex:1] intValue])];
2458 yString = (NSString *)[tokens objectAtIndex:2];
2459 if ([yString hasPrefix:@"rand:"])
2460 yString = [NSString stringWithFormat:@"%.3f", bellf([(NSString*)[[yString componentsSeparatedByString:@":"] objectAtIndex:1] intValue])];
2461 zString = (NSString *)[tokens objectAtIndex:3];
2462 if ([zString hasPrefix:@"rand:"])
2463 zString = [NSString stringWithFormat:@"%.3f", bellf([(NSString*)[[zString componentsSeparatedByString:@":"] objectAtIndex:1] intValue])];
2464
2465 HPVector posn = make_HPvector([xString floatValue], [yString floatValue], [zString floatValue]);
2466 GLfloat scalar = 1.0;
2467
2468 coordinates = [UNIVERSE coordinatesForPosition:posn withCoordinateSystem:systemString returningScalar:&scalar];
2469
2470 [shipAI message:@"APPROACH_COORDINATES"];
2471}

◆ setCoordinatesFromPosition

- (void) setCoordinatesFromPosition
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1222{
1223 coordinates = position;
1224}

◆ setCourseToPlanet

- (void) setCourseToPlanet
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1306{
1307 /*- selects the nearest planet it can find -*/
1308 OOPlanetEntity *the_planet = [self findNearestPlanetExcludingMoons];
1309 if (the_planet)
1310 {
1311 double variation = (aegis_status == AEGIS_NONE ? 0.5 : 0.2); // more random deviation when far from planet.
1312 HPVector p_pos = the_planet->position;
1313 double p_cr = the_planet->collision_radius; // the surface
1314 HPVector p1 = HPvector_between(p_pos, position);
1315 p1 = HPvector_normal(p1); // vector towards ship
1316 p1.x += variation * (randf() - variation);
1317 p1.y += variation * (randf() - variation);
1318 p1.z += variation * (randf() - variation);
1319 p1 = HPvector_normal(p1);
1320 _destination = HPvector_add(p_pos, HPvector_multiply_scalar(p1, p_cr)); // on surface
1321 desired_range = collision_radius + 100.0; // +100m from the destination
1322 }
1323 else
1324 {
1325 [shipAI message:@"NO_PLANET_FOUND"];
1326 }
1327}

◆ setCourseToWitchpoint

- (void) setCourseToWitchpoint
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1599{
1600 if (UNIVERSE)
1601 {
1602 _destination = [UNIVERSE getWitchspaceExitPosition];
1603 desired_range = 10000.0; // 10km away
1604 }
1605}

◆ setCrew:

- (void) setCrew: (NSArray *)  crewArray

Definition at line 7616 of file ShipEntity.m.

7948 :(NSArray *)crewArray
7949{
7950 if ([self isExplicitlyUnpiloted])
7951 {
7952 //unpiloted ships cannot have crew
7953 // but may have crew before isExplicitlyUnpiloted set, so force *that* to clear too
7954 [crew autorelease];
7955 crew = nil;
7956 return;
7957 }
7958 //do not set to hulk here when crew is nil (or 0). Some things like missiles have no crew.
7959 [crew autorelease];
7960 crew = [crewArray copy];
7961}
BOOL isExplicitlyUnpiloted()

Referenced by ShipSetCrew().

+ Here is the caller graph for this function:

◆ setDemoShip:

- (void) setDemoShip: (OOScalar demoRate

Definition at line 14062 of file ShipEntity.m.

14593 : (OOScalar) rate
14594{
14596 demoRate = rate;
14597 isDemoShip = YES;
14598 [self setPitch: 0.0f];
14599 [self setRoll: 0.0f];
14600}
BOOL isDemoShip
Definition ShipEntity.h:493
Quaternion demoStartOrientation
Definition ShipEntity.h:496
OOScalar demoRate
Definition ShipEntity.h:494

◆ setDemoStartTime:

- (void) setDemoStartTime: (OOTimeAbsolute time

Definition at line 14062 of file ShipEntity.m.

14607 : (OOTimeAbsolute) time
14608{
14609 demoStartTime = time;
14610}

◆ setDesiredRange:

- (void) setDesiredRange: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8599 :(double) amount
8600{
8601 desired_range = amount;
8602}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setDesiredRangeForWaypoint

- (void) setDesiredRangeForWaypoint
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

913{
914 desired_range = fmax(maxFlightSpeed / max_flight_pitch / 6, 50.0); // some ships need a longer range to reach a waypoint.
915}

◆ setDesiredRangeTo:

- (void) setDesiredRangeTo: (NSString *)  rangeString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

907 :(NSString *)rangeString
908{
909 desired_range = [rangeString doubleValue];
910}

◆ setDesiredSpeed:

- (void) setDesiredSpeed: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8581 :(double) amount
8582{
8583 desired_speed = amount;
8584}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setDestination:

- (void) setDestination: (HPVector)  dest

Definition at line 9589 of file ShipEntity.m.

13666 :(HPVector) dest
13667{
13668 _destination = dest;
13669 frustration = 0.0; // new destination => no frustration!
13670}

◆ setDestinationFromCoordinates

- (void) setDestinationFromCoordinates
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1216{
1217 _destination = coordinates;
1218}

◆ setDestinationSystem:

- (void) setDestinationSystem: (OOSystemID s

Definition at line 7616 of file ShipEntity.m.

7920 :(OOSystemID)s
7921{
7923}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setDestinationToCurrentLocation

- (void) setDestinationToCurrentLocation
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

893{
894 // randomly add a .5m variance
895 _destination = HPvector_add(position, OOHPVectorRandomSpatial(0.5));
896}
HPVector OOHPVectorRandomSpatial(OOHPScalar maxLength)
Definition OOHPVector.m:82

◆ setDestinationToDockingAbort

- (void) setDestinationToDockingAbort
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2205{
2206 Entity *the_target = [self targetStation];
2207 if (!the_target) {
2208 /* Probably the player trying to dock with docking computer
2209 * from out of scanner range */
2210 the_target = [UNIVERSE station];
2211 }
2212 double bo_distance = 8000; // 8km back off
2213 HPVector v0 = position;
2214 HPVector d0 = (the_target) ? the_target->position : kZeroHPVector;
2215 v0.x += (randf() - 0.5)*collision_radius; v0.y += (randf() - 0.5)*collision_radius; v0.z += (randf() - 0.5)*collision_radius;
2216 v0.x -= d0.x; v0.y -= d0.y; v0.z -= d0.z;
2217 v0 = HPvector_normal_or_fallback(v0, make_HPvector(0, 0, -1));
2218
2219 v0.x *= bo_distance; v0.y *= bo_distance; v0.z *= bo_distance;
2220 v0.x += d0.x; v0.y += d0.y; v0.z += d0.z;
2221 coordinates = v0;
2222 _destination = v0;
2223}

◆ setDestinationToJinkPosition

- (void) setDestinationToJinkPosition
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

900{
901 Vector front = vector_multiply_scalar([self forwardVector], flightSpeed / max_flight_pitch * 2);
902 _destination = HPvector_add(position, vectorToHPVector(vector_add(front, OOVectorRandomSpatial(100))));
903 pitching_over = YES; // don't complete roll first, but immediately start with pitching.
904}
Vector OOVectorRandomSpatial(OOScalar maxLength)
Definition OOVector.m:99

◆ setDestinationToStationBeacon

- (void) setDestinationToStationBeacon
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1615{
1616 if ([UNIVERSE station])
1617 {
1618 _destination = [[UNIVERSE station] beaconPosition];
1619 }
1620}

◆ setDestinationToTarget

- (void) setDestinationToTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1420{
1421 Entity *the_target = [self primaryTarget];
1422 if (the_target)
1423 _destination = the_target->position;
1424}

◆ setDestinationToWitchpoint

- (void) setDestinationToWitchpoint
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1609{
1610 _destination = [UNIVERSE getWitchspaceExitPosition];
1611}

◆ setDestinationWithinTarget

- (void) setDestinationWithinTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1428{
1429 Entity *the_target = [self primaryTarget];
1430 if (the_target)
1431 {
1432 HPVector pos = the_target->position;
1433 Quaternion q; quaternion_set_random(&q);
1434 Vector v = vector_forward_from_quaternion(q);
1435 GLfloat d = (randf() - randf()) * the_target->collision_radius;
1436 _destination = make_HPvector(pos.x + d * v.x, pos.y + d * v.y, pos.z + d * v.z);
1437 }
1438}

◆ setDisplayName:

- (void) setDisplayName: (NSString *)  inName

Definition at line 6493 of file ShipEntity.m.

7226 :(NSString *)inName
7227{
7228 [displayName release];
7229 displayName = [inName copy];
7230}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setEnergyRechargeRate:

- (void) setEnergyRechargeRate: (GLfloat)  new

Definition at line 7408 of file ShipEntity.m.

7505 :(GLfloat)new
7506{
7508}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setEntityPersonalityInt:

- (void) setEntityPersonalityInt: (uint16_t)  value

Definition at line 9589 of file ShipEntity.m.

9779 :(uint16_t)value
9780{
9781 if (value <= ENTITY_PERSONALITY_MAX)
9782 {
9783 entity_personality = value;
9784 [[self mesh] rebindMaterials];
9785 }
9786}

Referenced by MissionRunScreen(), PlayerReplaceShip(), and ShipSetProperty().

+ Here is the caller graph for this function:

◆ setEscortDestination:

- (void) setEscortDestination: (HPVector)  dest

Definition at line 9589 of file ShipEntity.m.

13673 :(HPVector) dest
13674{
13675 _destination = dest; // don't reset frustration for escorts.
13676}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setEscortGroup:

- (void) setEscortGroup: (OOShipGroup *)  group

Definition at line 6493 of file ShipEntity.m.

6941 :(OOShipGroup *)group
6942{
6943 if (group != _escortGroup)
6944 {
6945 [_escortGroup release];
6946 _escortGroup = [group retain];
6947 [group setLeader:self]; // A ship is always leader of its own escort group.
6948 [self updateEscortFormation];
6949 }
6950}
void setLeader:(ShipEntity *leader)

◆ setEvasiveJink:

- (void) setEvasiveJink: (GLfloat)  z

Definition at line 9589 of file ShipEntity.m.

10403 :(GLfloat) z
10404{
10406 {
10407 jink = kZeroVector;
10408 }
10409 else
10410 {
10411 jink.x = (ranrot_rand() % 256) - 128.0;
10412 jink.y = (ranrot_rand() % 256) - 128.0;
10413 jink.z = z;
10414
10415 // make sure we don't accidentally have near-zero jink
10416 if (jink.x < 0.0)
10417 {
10418 jink.x -= 128.0;
10419 }
10420 else
10421 {
10422 jink.x += 128.0;
10423 }
10424 if (jink.y < 0)
10425 {
10426 jink.y -= 128.0;
10427 }
10428 else
10429 {
10430 jink.y += 128.0;
10431 }
10432 }
10433}

◆ setExhaustEmissiveColor:

- (void) setExhaustEmissiveColor: (OOColor *)  color

Definition at line 9589 of file ShipEntity.m.

11700 :(OOColor *) color
11701{
11702 if (color)
11703 {
11704 [exhaust_emissive_color release];
11705 exhaust_emissive_color = [color retain];
11706 }
11707}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setFoundTarget:

- (void) setFoundTarget: (Entity *)  targetEntity

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

9924 :(Entity *) targetEntity
9925{
9926 [_foundTarget release];
9927 _foundTarget = [targetEntity weakRetain];
9928}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setFuel:

- (void) setFuel: (OOFuelQuantity amount

Definition at line 7616 of file ShipEntity.m.

8107 :(OOFuelQuantity) amount
8108{
8109 if (amount > [self fuelCapacity]) amount = [self fuelCapacity];
8110
8111 fuel = amount;
8112}
uint16_t OOFuelQuantity
Definition OOTypes.h:179

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setGroup:

- (void) setGroup: (OOShipGroup *)  group

Definition at line 6493 of file ShipEntity.m.

6911 :(OOShipGroup *)group
6912{
6913 if (group != _group)
6914 {
6915 if (_escortGroup != _group)
6916 {
6917 if (self == [_group leader]) [_group setLeader:nil];
6918 [_group removeShip:self];
6919 }
6920 [_group release];
6921 [group addShip:self];
6922 _group = [group retain];
6923
6924 [[group leader] updateEscortFormation];
6925 }
6926}
BOOL addShip:(ShipEntity *ship)
void updateEscortFormation()

Referenced by ShipGroupAddShip(), and ShipSetProperty().

+ Here is the caller graph for this function:

◆ setHeatInsulation:

- (void) setHeatInsulation: (GLfloat)  value

Definition at line 7616 of file ShipEntity.m.

8824 :(GLfloat) value
8825{
8826 _heatInsulation = value;
8827}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setHomeSystem:

- (void) setHomeSystem: (OOSystemID s

Definition at line 7616 of file ShipEntity.m.

7914 :(OOSystemID)s
7915{
7916 home_system = s;
7917}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setHulk:

- (void) setHulk: (BOOL)  isNowHulk

Definition at line 7616 of file ShipEntity.m.

8963 :(BOOL)isNowHulk
8964{
8965 if (![self isSubEntity])
8966 {
8967 isHulk = isNowHulk;
8968 }
8969}

◆ setHyperspaceSpinTime:

- (void) setHyperspaceSpinTime: (float)  new

Definition at line 2092 of file ShipEntity.m.

3218 :(float)new
3219{
3221}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setIsBoulder:

- (void) setIsBoulder: (BOOL)  flag

Definition at line 14942 of file ShipEntity.m.

1659 :(BOOL)flag
1660{
1661 if (flag) [self addRole:kBoulderRole];
1662 else [self removeRole:kBoulderRole];
1663}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setIsMissileFlag:

- (void) setIsMissileFlag: (BOOL)  newValue

Definition at line 9589 of file ShipEntity.m.

12316 :(BOOL)newValue
12317{
12318 isMissile = !!newValue; // set the isMissile flag, used for tracking submunitions and preventing collisions at launch.
12319}

◆ setIsWreckage:

- (void) setIsWreckage: (BOOL)  isw

Definition at line 7616 of file ShipEntity.m.

9155 :(BOOL)isw
9156{
9157 isWreckage = isw;
9158}

◆ setLaserColor:

- (void) setLaserColor: (OOColor *)  color

Definition at line 9589 of file ShipEntity.m.

11690 :(OOColor *) color
11691{
11692 if (color)
11693 {
11694 [laser_color release];
11695 laser_color = [color retain];
11696 }
11697}

◆ setLastAegisLock:

- (void) setLastAegisLock: (Entity<OOStellarBody> *)  lastAegisLock

Definition at line 7616 of file ShipEntity.m.

7896{
7897 [_lastAegisLock release];
7898 _lastAegisLock = [lastAegisLock weakRetain];
7899}

◆ setLastEscortTarget:

- (void) setLastEscortTarget: (Entity *)  targetEntity

Definition at line 9589 of file ShipEntity.m.

9962 :(Entity *) targetEntity
9963{
9964 [_lastEscortTarget release];
9965 _lastEscortTarget = [targetEntity weakRetain];
9966}

◆ setLaunchDelay:

- (void) setLaunchDelay: (double)  delay

Definition at line 7616 of file ShipEntity.m.

7936 :(double)delay
7937{
7938 launch_delay = delay;
7939}
double launch_delay
Definition ShipEntity.h:345

◆ setMaxAvailableCargoSpace:

- (void) setMaxAvailableCargoSpace: (OOCargoQuantity new

Definition at line 7616 of file ShipEntity.m.

8371 :(OOCargoQuantity)new
8372{
8374}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setMaxEscortCount:

- (void) setMaxEscortCount: (uint8_t)  newCount

Definition at line 6493 of file ShipEntity.m.

7019 :(uint8_t)newCount
7020{
7021 _maxEscortCount = newCount;
7022}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setMaxFlightPitch:

- (void) setMaxFlightPitch: (GLfloat)  new

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8750 :(GLfloat)new
8751{
8752 max_flight_pitch = new;
8753}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setMaxFlightRoll:

- (void) setMaxFlightRoll: (GLfloat)  new

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8762 :(GLfloat)new
8763{
8764 max_flight_roll = new;
8765}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setMaxFlightSpeed:

- (void) setMaxFlightSpeed: (GLfloat)  new

Definition at line 7616 of file ShipEntity.m.

8756 :(GLfloat)new
8757{
8758 maxFlightSpeed = new;
8759}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setMaxFlightYaw:

- (void) setMaxFlightYaw: (GLfloat)  new

Reimplemented in PlayerEntity.

Definition at line 7616 of file ShipEntity.m.

8768 :(GLfloat)new
8769{
8770 max_flight_yaw = new;
8771}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setMaxThrust:

- (void) setMaxThrust: (GLfloat)  new

Definition at line 2092 of file ShipEntity.m.

4122 :(GLfloat)new
4123{
4124 max_thrust = new;
4125}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setMesh:

- (void) setMesh: (OOMesh *)  mesh

Definition at line 14942 of file ShipEntity.m.

1254 :(OOMesh *)mesh
1255{
1256 if (mesh != [self mesh])
1257 {
1258 [self setDrawable:mesh];
1259 [octree autorelease];
1260 octree = [[mesh octree] retain];
1261 }
1262}
Octree * octree
Definition OOMesh.h:122

Referenced by ShipSetMaterialsInternal().

+ Here is the caller graph for this function:

◆ setMessageTime:

- (void) setMessageTime: (double)  value

Definition at line 6493 of file ShipEntity.m.

6899 :(double) value
6900{
6901 messageTime = value;
6902}

◆ setMissileLoadTime:

- (void) setMissileLoadTime: (OOTimeDelta newMissileLoadTime

Definition at line 9589 of file ShipEntity.m.

12328 :(OOTimeDelta)newMissileLoadTime
12329{
12330 missile_load_time = fmax(0.0, newMissileLoadTime);
12331}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setName:

- (void) setName: (NSString *)  inName

Reimplemented in PlayerEntity.

Definition at line 6493 of file ShipEntity.m.

7205 :(NSString *)inName
7206{
7207 [name release];
7208 name = [inName copy];
7209}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setNextBeacon:

- (void) setNextBeacon: (Entity <OOBeaconEntity> *)  beaconShip
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1647 :(Entity <OOBeaconEntity> *)beaconShip
1648{
1649 if (beaconShip != [self nextBeacon])
1650 {
1651 [_nextBeacon release];
1652 _nextBeacon = [beaconShip weakRetain];
1653 }
1654}
Entity< OOBeaconEntity > * nextBeacon()
OOWeakReference * _nextBeacon
Definition ShipEntity.h:487

◆ setOwner:

- (void) setOwner: (Entity *)  who_owns_entity
implementation

Reimplemented from Entity.

Definition at line 6493 of file ShipEntity.m.

6718 :(Entity *)who_owns_entity
6719{
6720 [super setOwner:who_owns_entity];
6721
6722 /* Reset shader binding target so that bind-to-super works.
6723 This is necessary since we don't know about the owner in
6724 setUpShipFromDictionary:, when the mesh is initially set up.
6725 -- Ahruman 2008-04-19
6726 */
6727 if (isSubEntity)
6728 {
6729 [[self drawable] setBindingTarget:self];
6730 }
6731}

◆ setPendingEscortCount:

- (void) setPendingEscortCount: (uint8_t)  count

Definition at line 6493 of file ShipEntity.m.

7007 :(uint8_t)count
7008{
7010}

◆ setPitch:

- (void) setPitch: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8219 :(double) amount
8220{
8221 flightPitch = amount * M_PI / 2.0;
8222}
#define M_PI
Definition OOMaths.h:73

◆ setPlanetPatrolCoordinates

- (void) setPlanetPatrolCoordinates
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1931{
1932 // check we've arrived near the last given coordinates
1933 HPVector r_pos = HPvector_subtract(position, coordinates);
1934 if (HPmagnitude2(r_pos) < 1000000 || patrol_counter == 0)
1935 {
1936 Entity *the_sun = [UNIVERSE sun];
1937 ShipEntity *the_station = [[self group] leader];
1938 if(!the_station || ![the_station isStation]) the_station = [UNIVERSE station];
1939 if ((!the_sun)||(!the_station))
1940 return;
1941 HPVector sun_pos = the_sun->position;
1942 HPVector stn_pos = the_station->position;
1943 HPVector sun_dir = HPvector_subtract(sun_pos,stn_pos);
1944 Vector vSun = make_vector(0, 0, 1);
1945 if (sun_dir.x||sun_dir.y||sun_dir.z)
1946 vSun = HPVectorToVector(HPvector_normal(sun_dir));
1947 Vector v0 = [the_station forwardVector];
1948 Vector v1 = cross_product(v0, vSun);
1949 Vector v2 = cross_product(v0, v1);
1950 switch (patrol_counter)
1951 {
1952 case 0: // first go to 5km ahead of the station
1953 coordinates = make_HPvector(stn_pos.x + 5000 * v0.x, stn_pos.y + 5000 * v0.y, stn_pos.z + 5000 * v0.z);
1954 desired_range = 250.0;
1955 break;
1956 case 1: // go to 25km N of the station
1957 coordinates = make_HPvector(stn_pos.x + 25000 * v1.x, stn_pos.y + 25000 * v1.y, stn_pos.z + 25000 * v1.z);
1958 desired_range = 250.0;
1959 break;
1960 case 2: // go to 25km E of the station
1961 coordinates = make_HPvector(stn_pos.x + 25000 * v2.x, stn_pos.y + 25000 * v2.y, stn_pos.z + 25000 * v2.z);
1962 desired_range = 250.0;
1963 break;
1964 case 3: // go to 25km S of the station
1965 coordinates = make_HPvector(stn_pos.x - 25000 * v1.x, stn_pos.y - 25000 * v1.y, stn_pos.z - 25000 * v1.z);
1966 desired_range = 250.0;
1967 break;
1968 case 4: // go to 25km W of the station
1969 coordinates = make_HPvector(stn_pos.x - 25000 * v2.x, stn_pos.y - 25000 * v2.y, stn_pos.z - 25000 * v2.z);
1970 desired_range = 250.0;
1971 break;
1972 default: // We should never come here
1973 coordinates = make_HPvector(stn_pos.x + 5000 * v0.x, stn_pos.y + 5000 * v0.y, stn_pos.z + 5000 * v0.z);
1974 desired_range = 250.0;
1975 break;
1976 }
1977 patrol_counter++;
1978 if (patrol_counter > 4)
1979 {
1980 if (randf() < .25)
1981 {
1982 // consider docking
1983 [self setTargetStation:the_station];
1984 [self setAITo:@"dockingAI.plist"];
1985 return;
1986 }
1987 else
1988 {
1989 // go around again
1990 patrol_counter = 1;
1991 }
1992 }
1993 }
1994 [shipAI message:@"APPROACH_COORDINATES"];
1995}

◆ setPrevBeacon:

- (void) setPrevBeacon: (Entity <OOBeaconEntity> *)  beaconShip
implementation

Reimplemented from <OOBeaconEntity>.

Definition at line 14942 of file ShipEntity.m.

1637 :(Entity <OOBeaconEntity> *)beaconShip
1638{
1639 if (beaconShip != [self prevBeacon])
1640 {
1641 [_prevBeacon release];
1642 _prevBeacon = [beaconShip weakRetain];
1643 }
1644}
OOWeakReference * _prevBeacon
Definition ShipEntity.h:486
Entity< OOBeaconEntity > * prevBeacon()

◆ setPrimaryAggressor:

- (void) setPrimaryAggressor: (Entity *)  targetEntity

Definition at line 9589 of file ShipEntity.m.

9943 :(Entity *) targetEntity
9944{
9945 [_primaryAggressor release];
9946 _primaryAggressor = [targetEntity weakRetain];
9947}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setPrimaryRole:

- (void) setPrimaryRole: (NSString *)  role

Definition at line 6493 of file ShipEntity.m.

7314 :(NSString *)role
7315{
7316 if (![role isEqual:primaryRole])
7317 {
7318 [primaryRole release];
7319 primaryRole = [role copy];
7320 }
7321}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setProximityAlert:

- (void) setProximityAlert: (ShipEntity *)  targetEntity

Definition at line 6493 of file ShipEntity.m.

7052 :(ShipEntity*) other
7053{
7054 if (!other)
7055 {
7057 return;
7058 }
7059
7060 if ([other mass] < 2000) // we are not alerted by small objects. (a cargopod has a mass of about 1000)
7061 return;
7062
7063
7064 if (isStation) // stations don't worry about colliding with things
7065 return;
7066
7067 /* Ignore station collision warnings if launching or docking */
7068 if ((other->isStation) && ([self status] == STATUS_LAUNCHING ||
7070 {
7071 return;
7072 }
7073
7074 if (!crew) // Ships without pilot (cargo, rocks, missiles, buoys etc) will not get alarmed. (escape-pods have pilots)
7075 return;
7076
7077 // check vectors
7078 Vector vdiff = HPVectorToVector(HPvector_between(position, other->position));
7079 GLfloat d_forward = dot_product(vdiff, v_forward);
7080 GLfloat d_up = dot_product(vdiff, v_up);
7081 GLfloat d_right = dot_product(vdiff, v_right);
7082 if ((d_forward > 0.0)&&(flightSpeed > 0.0)) // it's ahead of us and we're moving forward
7083 d_forward *= 0.25 * maxFlightSpeed / flightSpeed; // extend the collision zone forward up to 400%
7084 double d2 = d_forward * d_forward + d_up * d_up + d_right * d_right;
7085 double cr2 = collision_radius * 2.0 + other->collision_radius; cr2 *= cr2; // check with twice the combined radius
7086
7087 if (d2 > cr2) // we're okay
7088 return;
7089
7090 if (behaviour == BEHAVIOUR_AVOID_COLLISION) // already avoiding something
7091 {
7092 ShipEntity* prox = (ShipEntity*)[self proximityAlert];
7093 if ((prox)&&(prox != other))
7094 {
7095 // check which subtends the greatest angle
7096 GLfloat sa_prox = prox->collision_radius * prox->collision_radius / HPdistance2(position, prox->position);
7097 GLfloat sa_other = other->collision_radius * other->collision_radius / HPdistance2(position, other->position);
7098 if (sa_prox < sa_other) return;
7099 }
7100 }
7101 [_proximityAlert release];
7102 _proximityAlert = [other weakRetain];
7103}

◆ setRacepointsFromTarget

- (void) setRacepointsFromTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2704{
2705 // two point - one at z - cr one at z + cr
2706 ShipEntity *ship = [self primaryTarget];
2707 if (ship == nil)
2708 {
2709 [shipAI message:@"NOTHING_FOUND"];
2710 return;
2711 }
2712 Vector k = ship->v_forward;
2713 GLfloat c = ship->collision_radius;
2714 HPVector o = ship->position;
2715 navpoints[0] = make_HPvector(o.x - c * k.x, o.y - c * k.y, o.z - c * k.z);
2716 navpoints[1] = make_HPvector(o.x + c * k.x, o.y + c * k.y, o.z + c * k.z);
2717 navpoints[2] = make_HPvector(o.x + 2.0 * c * k.x, o.y + 2.0 * c * k.y, o.z + 2.0 * c * k.z);
2718 number_of_navpoints = 2;
2719 next_navpoint_index = 0;
2720 _destination = navpoints[0];
2721 [shipAI message:@"RACEPOINTS_SET"];
2722}

◆ setRawRoll:

- (void) setRawRoll: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8213 :(double) amount
8214{
8215 flightRoll = amount;
8216}

Referenced by StationSetProperty().

+ Here is the caller graph for this function:

◆ setReactionTime:

- (void) setReactionTime: (float)  newReactionTime

Definition at line 2092 of file ShipEntity.m.

6290 : (float) newReactionTime
6291{
6292 reactionTime = newReactionTime;
6293}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setReference:

- (void) setReference: (Vector)  v

Definition at line 7408 of file ShipEntity.m.

7553 :(Vector) v
7554{
7555 reference = v;
7556}

◆ setRememberedShip:

- (void) setRememberedShip: (Entity *)  targetEntity

Definition at line 9589 of file ShipEntity.m.

10000 :(Entity *) targetEntity
10001{
10002 [_rememberedShip release];
10003 _rememberedShip = [targetEntity weakRetain];
10004}

◆ setReportAIMessages:

- (void) setReportAIMessages: (BOOL)  yn

Definition at line 7408 of file ShipEntity.m.

7565 :(BOOL) yn
7566{
7567 reportAIMessages = yn;
7568}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setRoll:

- (void) setRoll: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8207 :(double) amount
8208{
8209 flightRoll = amount * M_PI / 2.0;
8210}

◆ setScanDescription:

- (void) setScanDescription: (NSString *)  inName

Definition at line 6493 of file ShipEntity.m.

7233 :(NSString *)inName
7234{
7235 [scan_description release];
7236 scan_description = [inName copy];
7237}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setScannerDisplayColor1:

- (void) setScannerDisplayColor1: (OOColor *)  color1

Definition at line 6493 of file ShipEntity.m.

6607 :(OOColor *)color
6608{
6610
6611 if (color == nil) color = [OOColor colorWithDescription:[[self shipInfoDictionary] objectForKey:@"scanner_display_color1"]];
6612 scanner_display_color1 = [color retain];
6613}
OOColor * colorWithDescription:(id description)
Definition OOColor.m:127

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setScannerDisplayColor2:

- (void) setScannerDisplayColor2: (OOColor *)  color2

Definition at line 6493 of file ShipEntity.m.

6616 :(OOColor *)color
6617{
6619
6620 if (color == nil) color = [OOColor colorWithDescription:[[self shipInfoDictionary] objectForKey:@"scanner_display_color2"]];
6621 scanner_display_color2 = [color retain];
6622}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setScannerDisplayColorHostile1:

- (void) setScannerDisplayColorHostile1: (OOColor *)  color1

Definition at line 6493 of file ShipEntity.m.

6637 :(OOColor *)color
6638{
6640
6641 if (color == nil) color = [OOColor colorWithDescription:[[self shipInfoDictionary] objectForKey:@"scanner_hostile_display_color1"]];
6642 scanner_display_color_hostile1 = [color retain];
6643}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setScannerDisplayColorHostile2:

- (void) setScannerDisplayColorHostile2: (OOColor *)  color2

Definition at line 6493 of file ShipEntity.m.

6646 :(OOColor *)color
6647{
6649
6650 if (color == nil) color = [OOColor colorWithDescription:[[self shipInfoDictionary] objectForKey:@"scanner_hostile_display_color2"]];
6651 scanner_display_color_hostile2 = [color retain];
6652}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setScannerRange:

- (void) setScannerRange: (GLfloat)  value

Definition at line 7408 of file ShipEntity.m.

7541 : (GLfloat) value
7542{
7543 scannerRange = value;
7544}

◆ setScriptedMisjump:

- (void) setScriptedMisjump: (BOOL)  newValue

Definition at line 14942 of file ShipEntity.m.

1295 :(BOOL)newValue
1296{
1297 scripted_misjump = !!newValue;
1298}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setScriptedMisjumpRange:

- (void) setScriptedMisjumpRange: (GLfloat)  newValue

Definition at line 14942 of file ShipEntity.m.

1307 :(GLfloat)newValue
1308{
1309 _scriptedMisjumpRange = newValue;
1310}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setShipClassName:

- (void) setShipClassName: (NSString *)  inName

Definition at line 6493 of file ShipEntity.m.

7219 :(NSString *)inName
7220{
7221 [shipClassName release];
7222 shipClassName = [inName copy];
7223}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setShipDataKey:

- (void) setShipDataKey: (NSString *)  key

Definition at line 14942 of file ShipEntity.m.

1985 :(NSString *)key
1986{
1988 _shipKey = [key copy];
1989}

◆ setShipHitByLaser:

- (void) setShipHitByLaser: (ShipEntity *)  ship
implementation

Provided by category ShipEntity(Private).

Definition at line 9589 of file ShipEntity.m.

10176 :(ShipEntity *)ship
10177{
10178 if (ship != [self shipHitByLaser])
10179 {
10180 [_shipHitByLaser release];
10181 _shipHitByLaser = [ship weakRetain];
10182 }
10183}
OOWeakReference * _shipHitByLaser
Definition ShipEntity.h:481
ShipEntity * shipHitByLaser()

◆ setShipScript:

- (void) setShipScript: (NSString *)  script_name

Definition at line 7616 of file ShipEntity.m.

8035 :(NSString *)script_name
8036{
8037 NSMutableDictionary *properties = nil;
8038 NSArray *actions = nil;
8039
8040 properties = [NSMutableDictionary dictionary];
8041 [properties setObject:self forKey:@"ship"];
8042
8043 [script autorelease];
8044 script = [OOScript jsScriptFromFileNamed:script_name properties:properties];
8045
8046 if (script == nil)
8047 {
8048 actions = [shipinfoDictionary oo_arrayForKey:@"launch_actions"];
8049 if (actions)
8050 {
8051 OOStandardsDeprecated([NSString stringWithFormat:@"The launch_actions ship key is deprecated on %@.",[self displayName]]);
8052 if (!OOEnforceStandards())
8053 {
8054 [properties setObject:actions forKey:@"legacy_launchActions"];
8055 }
8056 }
8057
8058 actions = [shipinfoDictionary oo_arrayForKey:@"script_actions"];
8059 if (actions)
8060 {
8061 OOStandardsDeprecated([NSString stringWithFormat:@"The script_actions ship key is deprecated on %@.",[self displayName]]);
8062 if (!OOEnforceStandards())
8063 {
8064 [properties setObject:actions forKey:@"legacy_scriptActions"];
8065 }
8066 }
8067
8068 actions = [shipinfoDictionary oo_arrayForKey:@"death_actions"];
8069 if (actions)
8070 {
8071 OOStandardsDeprecated([NSString stringWithFormat:@"The death_actions ship key is deprecated on %@.",[self displayName]]);
8072 if (!OOEnforceStandards())
8073 {
8074 [properties setObject:actions forKey:@"legacy_deathActions"];
8075 }
8076 }
8077
8078 actions = [shipinfoDictionary oo_arrayForKey:@"setup_actions"];
8079 if (actions)
8080 {
8081 OOStandardsDeprecated([NSString stringWithFormat:@"The setup_actions ship key is deprecated on %@.",[self displayName]]);
8082 if (!OOEnforceStandards())
8083 {
8084 [properties setObject:actions forKey:@"legacy_setupActions"];
8085 }
8086 }
8087
8088 script = [OOScript jsScriptFromFileNamed:@"oolite-default-ship-script.js"
8089 properties:properties];
8090 }
8091 [script retain];
8092}
BOOL OOEnforceStandards(void)
id jsScriptFromFileNamed:properties:(NSString *fileName,[properties] NSDictionary *properties)
Definition OOScript.m:191

Referenced by ShipSetScript().

+ Here is the caller graph for this function:

◆ setShipUniqueName:

- (void) setShipUniqueName: (NSString *)  inName

Definition at line 6493 of file ShipEntity.m.

7212 :(NSString *)inName
7213{
7214 [shipUniqueName release];
7215 shipUniqueName = [inName copy];
7216}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setSingleCrewWithRole:

- (void) setSingleCrewWithRole: (NSString *)  crewRole

Convenience to set the crew to a single character of the given role, originating in the ship's home system. Does nothing if unpiloted.

Definition at line 7616 of file ShipEntity.m.

7964 :(NSString *)crewRole
7965{
7966 if (![self isUnpiloted])
7967 {
7968 OOCharacter *crewMember = [OOCharacter randomCharacterWithRole:crewRole
7969 andOriginalSystem:[self homeSystem]];
7970 [self setCrew:[NSArray arrayWithObject:crewMember]];
7971 }
7972}
BOOL isUnpiloted()

◆ setSpeed:

- (void) setSpeed: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8575 :(double) amount
8576{
8577 flightSpeed = amount;
8578}

◆ setSpeedFactorTo:

- (void) setSpeedFactorTo: (NSString *)  speedString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

923 :(NSString *)speedString
924{
925 desired_speed = maxFlightSpeed * [speedString doubleValue];
926}

◆ setSpeedTo:

- (void) setSpeedTo: (NSString *)  speedString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

917 :(NSString *)speedString
918{
919 desired_speed = [speedString doubleValue];
920}

◆ setSpeedToCruiseSpeed

- (void) setSpeedToCruiseSpeed
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

929{
930 desired_speed = cruiseSpeed;
931}

◆ setStateMachine:

- (void) setStateMachine: (NSString *)  ai_desc

Definition at line 7616 of file ShipEntity.m.

7993 :(NSString *)smName
7994{
7995 [self setAITo:smName];
7996}

◆ setStateTo:

- (void) setStateTo: (NSString *)  state
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

842 :(NSString *)state
843{
844 [[self getAI] setState:state];
845}

◆ setStatus:

- (void) setStatus: (OOEntityStatus stat
implementation

Reimplemented from Entity.

Definition at line 7616 of file ShipEntity.m.

7926 :(OOEntityStatus) stat
7927{
7928 if ([self status] == stat) return;
7929 [super setStatus:stat];
7930 if (stat == STATUS_LAUNCHING)
7931 {
7932 launch_time = [UNIVERSE getTime];
7933 }
7934}
double launch_time
Definition ShipEntity.h:344

Referenced by PlayerShipBeginGalacticHyperspaceCountdown().

+ Here is the caller graph for this function:

◆ setSubEntityRotationalVelocity:

- (void) setSubEntityRotationalVelocity: (Quaternion)  rv

Definition at line 14942 of file ShipEntity.m.

1175 :(Quaternion)rv
1176{
1178}
Quaternion subentityRotationalVelocity
Definition ShipEntity.h:219

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setSubEntityTakingDamage:

- (void) setSubEntityTakingDamage: (ShipEntity *)  sub

Definition at line 14942 of file ShipEntity.m.

1372 :(ShipEntity *)sub
1373{
1374#ifndef NDEBUG
1375 // Sanity checks: sub must be a ship subentity of self, or nil.
1376 if (sub != nil)
1377 {
1378 if (![self hasSubEntity:sub])
1379 {
1380 OOLog(@"ship.subentity.sanityCheck.failed.details", @"Attempt to set subentity taking damage of %@ to %@, which is not a subentity.", [self shortDescription], sub);
1381 sub = nil;
1382 }
1383 else if (![sub isShip])
1384 {
1385 OOLog(@"ship.subentity.sanityCheck.failed", @"Attempt to set subentity taking damage of %@ to %@, which is not a ship.", [self shortDescription], sub);
1386 sub = nil;
1387 }
1388 }
1389#endif
1390
1391 [_subEntityTakingDamage release];
1393}
OOWeakReference * _subEntityTakingDamage
Definition ShipEntity.h:457

◆ setSubIdx:

- (void) setSubIdx: (NSUInteger)  value

Definition at line 14942 of file ShipEntity.m.

780 :(NSUInteger)value
781{
782 _subIdx = value;
783}
NSUInteger _subIdx
Definition ShipEntity.h:342

◆ setSunGlareFilter:

- (void) setSunGlareFilter: (GLfloat)  newValue

Definition at line 14942 of file ShipEntity.m.

1211 :(GLfloat)newValue
1212{
1213 sunGlareFilter = OOClamp_0_1_f(newValue);
1214}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setSunSkimEndCoordinates

- (void) setSunSkimEndCoordinates
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2021{
2022 if ([UNIVERSE sun] == nil)
2023 {
2024 [shipAI message:@"NO_SUN_FOUND"];
2025 return;
2026 }
2027
2028 coordinates = [UNIVERSE getSunSkimEndPositionForShip:self];
2029 [shipAI message:@"APPROACH_COORDINATES"];
2030}

◆ setSunSkimExitCoordinates

- (void) setSunSkimExitCoordinates
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2034{
2035 Entity *the_sun = [UNIVERSE sun];
2036 if (the_sun == nil) return;
2037 HPVector v1 = [UNIVERSE getSunSkimEndPositionForShip:self];
2038 HPVector vs = the_sun->position;
2039 HPVector vout = HPvector_subtract(v1,vs);
2040 if (vout.x||vout.y||vout.z)
2041 vout = HPvector_normal(vout);
2042 else
2043 vout.z = 1.0;
2044 v1.x += 10000 * vout.x; v1.y += 10000 * vout.y; v1.z += 10000 * vout.z;
2045 coordinates = v1;
2046 [shipAI message:@"APPROACH_COORDINATES"];
2047}

◆ setSunSkimStartCoordinates

- (void) setSunSkimStartCoordinates
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1999{
2000 if ([UNIVERSE sun] == nil)
2001 {
2002 [shipAI message:@"NO_SUN_FOUND"];
2003 return;
2004 }
2005
2006 HPVector v0 = [UNIVERSE getSunSkimStartPositionForShip:self];
2007
2008 if (!HPvector_equal(v0, kZeroHPVector))
2009 {
2010 coordinates = v0;
2011 [shipAI message:@"APPROACH_COORDINATES"];
2012 }
2013 else
2014 {
2015 [shipAI message:@"WAIT_FOR_SUN"];
2016 }
2017}

◆ setSuppressExplosion:

- (void) setSuppressExplosion: (BOOL)  suppress

Definition at line 9589 of file ShipEntity.m.

9789 :(BOOL)suppress
9790{
9791 suppressExplosion = !!suppress;
9792}

◆ setTakeOffFromPlanet

- (void) setTakeOffFromPlanet
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1331{
1332 /*- selects the nearest planet it can find -*/
1333 OOPlanetEntity *the_planet = [self findNearestPlanet];
1334 if (the_planet)
1335 {
1336 _destination = HPvector_add([the_planet position], HPvector_multiply_scalar(
1337 HPvector_normal(HPvector_subtract([the_planet position],position)),-10000.0-the_planet->collision_radius));// 10km straight up
1338 desired_range = 50.0;
1339 }
1340 else
1341 {
1342 OOLog(@"ai.setTakeOffFromPlanet.noPlanet", @"%@", @"***** Error. Planet not found during take off!");
1343 }
1344}

◆ setTargetForScript:

- (void) setTargetForScript: (ShipEntity *)  target

Provided by category ShipEntity(OOJavaScriptExtensions).

Definition at line 1 of file EntityOOJavaScriptExtensions.m.

140 :(ShipEntity *)target
141{
142 ShipEntity *me = self;
143
144 // Ensure coherence by not fiddling with subentities.
145 while ([me isSubEntity])
146 {
147 if (me == [me owner] || [me owner] == nil) break;
148 me = (ShipEntity *)[me owner];
149 }
150 while ([target isSubEntity])
151 {
152 if (target == [target owner] || [target owner] == nil) break;
153 target = (ShipEntity *)[target owner];
154 }
155 if (![me isKindOfClass:[ShipEntity class]]) return;
156 if (target != nil)
157 {
158 [me addTarget:target];
159 }
160 else [me removeTarget:[me primaryTarget]];
161}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setTargetStation:

- (void) setTargetStation: (Entity *)  targetEntity

Definition at line 9589 of file ShipEntity.m.

10019 :(Entity *) targetEntity
10020{
10021 [_targetStation release];
10022 _targetStation = [targetEntity weakRetain];
10023}
OOWeakReference * _targetStation
Definition ShipEntity.h:439

◆ setTargetToFoundTarget

- (void) setTargetToFoundTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1139{
1140 if ([self foundTarget] != nil)
1141 {
1142 [self addTarget:[self foundTarget]];
1143 }
1144 else
1145 {
1146 [shipAI message:@"TARGET_LOST"]; // to prevent the ship going for a wrong, previous target. Should not be a reactToMessage.
1147 }
1148}

◆ setTargetToLastStation

- (void) setTargetToLastStation
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2537{
2538 Entity *station = [self targetStation];
2539
2540 if (station != nil && [station isStation])
2541 {
2542 [self addTarget:station];
2543 }
2544 else
2545 {
2546 [shipAI message:@"NO_STATION_FOUND"];
2547 [self setTargetStation:nil];
2548 }
2549
2550}

◆ setTargetToNearestFriendlyStation

- (void) setTargetToNearestFriendlyStation

Definition at line 9589 of file ShipEntity.m.

13975{
13976 [self setTargetToNearestStationIncludingHostiles:NO];
13977}

◆ setTargetToNearestStation

- (void) setTargetToNearestStation

Definition at line 9589 of file ShipEntity.m.

13982{
13983 [self setTargetToNearestStationIncludingHostiles:YES];
13984}

◆ setTargetToNearestStationIncludingHostiles:

- (void) setTargetToNearestStationIncludingHostiles: (BOOL)  includeHostiles
implementation

Definition at line 9589 of file ShipEntity.m.

13923 :(BOOL) includeHostiles
13924{
13925 // check if the groupID (parent ship) points to a station...
13926 Entity *mother = [[self group] leader];
13927 if ([mother isStation])
13928 {
13929 [self addTarget:mother];
13930 [self setTargetStation:mother];
13931 return; // head for mother!
13932 }
13933
13934 /*- selects the nearest station it can find -*/
13935 if (!UNIVERSE)
13936 return;
13937 int ent_count = UNIVERSE->n_entities;
13938 Entity **uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
13939 Entity *my_entities[ent_count];
13940 int i;
13941 int station_count = 0;
13942 for (i = 0; i < ent_count; i++)
13943 if (uni_entities[i]->isStation)
13944 my_entities[station_count++] = [uni_entities[i] retain]; // retained
13945 //
13946 StationEntity *thing = nil, *station = nil;
13947 double range2, nearest2 = SCANNER_MAX_RANGE2 * 1000000.0; // 1000x typical scanner range (25600 km), squared.
13948 for (i = 0; i < station_count; i++)
13949 {
13950 thing = (StationEntity *)my_entities[i];
13951 range2 = HPdistance2(position, thing->position);
13952 if (range2 < nearest2 && (includeHostiles || ![thing isHostileTo:self]))
13953 {
13954 station = thing;
13955 nearest2 = range2;
13956 }
13957 }
13958 for (i = 0; i < station_count; i++)
13959 [my_entities[i] release]; // released
13960 //
13961 if (station)
13962 {
13963 [self addTarget:station];
13964 [self setTargetStation:station];
13965 }
13966 else
13967 {
13968 [shipAI message:@"NO_STATION_FOUND"];
13969 }
13970}

◆ setTargetToPrimaryAggressor

- (void) setTargetToPrimaryAggressor
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

940{
941 Entity *primeAggressor = [self primaryAggressor];
942 if (!primeAggressor)
943 return;
944 if ([self primaryTarget] == primeAggressor)
945 return;
946
947 // a more considered approach here:
948 // if we're already busy attacking a target we don't necessarily want to break off
949 //
950 if ([self hasHostileTarget] && randf() < 0.75) // if I'm attacking, ignore 75% of new aggressor's attacks
951 {
952 // but add them as a secondary target anyway
953 [self addDefenseTarget:(ShipEntity*)primeAggressor];
954 return;
955 }
956 // react only if the primary aggressor is not a friendly ship, else ignore it
957 if ([primeAggressor isShip] && ![(ShipEntity *)primeAggressor isFriendlyTo:self])
958 {
959 // inform our old target of our new target
960 //
961 Entity *primeTarget = [self primaryTarget];
962 if ((primeTarget)&&(primeTarget->isShip))
963 {
964 ShipEntity *currentShip = [self primaryTarget];
965 [[currentShip getAI] message:[NSString stringWithFormat:@"%@ %d %d", AIMS_AGGRESSOR_SWITCHED_TARGET, universalID, [[self primaryAggressor] universalID]]];
966 [currentShip doScriptEvent:OOJSID("shipAttackerDistracted") withArgument:[self primaryAggressor]];
967 }
968
969 // okay, so let's now target the aggressor
970 [self addTarget:[self primaryAggressor]];
971 }
972}

◆ setTargetToRandomStation

- (void) setTargetToRandomStation
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2484{
2485 /*- selects the nearest station it can find -*/
2486 int ent_count = UNIVERSE->n_entities;
2487 Entity **uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
2488 Entity *my_entities[ent_count];
2489 StationEntity *station = nil, *my_station = nil;
2490 double maxRange2 = desired_range * desired_range;
2491 int i;
2492 int station_count = 0;
2493
2494 for (i = 0; i < ent_count; i++)
2495 {
2496 // find stations within range but exclude carriers.
2497 if (uni_entities[i]->isStation)
2498 {
2499 my_station = (StationEntity*)uni_entities[i];
2500 if ([my_station maxFlightSpeed] == 0 && [my_station hasNPCTraffic] && HPdistance2(position, [my_station position]) < maxRange2)
2501 {
2502 my_entities[station_count++] = [uni_entities[i] retain]; // retained
2503 }
2504 }
2505 }
2506
2507 if (station_count != 0)
2508 {
2509 // select a random station
2510 station = (StationEntity *)my_entities[ranrot_rand() % station_count];
2511 // if more than one candidate do not select main station
2512 if (station == [UNIVERSE station] && station_count > 1)
2513 {
2514 while (station == [UNIVERSE station])
2515 {
2516 station = (StationEntity *)my_entities[ranrot_rand() % station_count];
2517 }
2518 }
2519 }
2520
2521 for (i = 0; i < station_count; i++)
2522 [my_entities[i] release]; // released
2523 //
2524 if (station)
2525 {
2526 [self addTarget:station];
2527 [self setTargetStation:station];
2528 [shipAI message:@"STATION_FOUND"];
2529 }
2530 else
2531 {
2532 [shipAI message:@"NO_STATION_IN_RANGE"];
2533 }
2534}

◆ setTargetToSystemStation

- (void) setTargetToSystemStation

Definition at line 9589 of file ShipEntity.m.

13989{
13990 StationEntity* system_station = [UNIVERSE station];
13991
13992 if (!system_station)
13993 {
13994 [shipAI message:@"NOTHING_FOUND"];
13995 [shipAI message:@"NO_STATION_FOUND"];
13997 [self setTargetStation:nil];
13998 return;
13999 }
14000
14001 if (!system_station->isStation)
14002 {
14003 [shipAI message:@"NOTHING_FOUND"];
14004 [shipAI message:@"NO_STATION_FOUND"];
14006 [self setTargetStation:nil];
14007 return;
14008 }
14009
14010 [self addTarget:system_station];
14011 [self setTargetStation:system_station];
14012 return;
14013}

◆ setTemperature:

- (void) setTemperature: (GLfloat)  value

Definition at line 7616 of file ShipEntity.m.

8787 :(GLfloat) value
8788{
8789 ship_temperature = value;
8790}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setThankedShip:

- (void) setThankedShip: (Entity *)  targetEntity

Definition at line 9589 of file ShipEntity.m.

9981 :(Entity *) targetEntity
9982{
9983 [_thankedShip release];
9984 _thankedShip = [targetEntity weakRetain];
9985}
OOWeakReference * _thankedShip
Definition ShipEntity.h:442

◆ setThrust:

- (void) setThrust: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8231 :(double) amount
8232{
8233 thrust = amount;
8234}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setThrustFactorTo:

- (void) setThrustFactorTo: (NSString *)  thrustFactorString
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

933 :(NSString *)thrustFactorString
934{
935 thrust = OOClamp_0_1_f([thrustFactorString doubleValue]) * max_thrust;
936}

◆ setThrustForDemo:

- (void) setThrustForDemo: (float)  factor

Definition at line 7616 of file ShipEntity.m.

8237 :(float) factor
8238{
8239 flightSpeed = factor * maxFlightSpeed;
8240}

◆ setTotalVelocity:

- (void) setTotalVelocity: (Vector)  vel

Definition at line 9589 of file ShipEntity.m.

12836 :(Vector)vel
12837{
12838 [self setVelocity:vector_subtract(vel, [self thrustVector])];
12839}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setTrackCloseContacts:

- (void) setTrackCloseContacts: (BOOL)  value

Definition at line 14062 of file ShipEntity.m.

14379 :(BOOL) value
14380{
14381 if (value == (BOOL)trackCloseContacts) return;
14382
14383 trackCloseContacts = value;
14384 [closeContactsInfo release];
14385
14387 {
14388 closeContactsInfo = [[NSMutableDictionary alloc] init];
14389 }
14390 else
14391 {
14393 }
14394}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setUpCargoType:

- (void) setUpCargoType: (NSString *)  cargoString

Definition at line 14942 of file ShipEntity.m.

1023 :(NSString *) cargoString
1024{
1025 cargo_type = StringToCargoType(cargoString);
1026
1027 switch (cargo_type)
1028 {
1029 case CARGO_SLAVES:
1030 commodity_amount = 1;
1032 commodity_type = @"slaves";
1033 cargo_type = CARGO_RANDOM; // not realy random, but it tells that cargo is selected.
1034 break;
1035
1036 case CARGO_ALLOY:
1037 commodity_amount = 1;
1039 commodity_type = @"alloys";
1041 break;
1042
1043 case CARGO_MINERALS:
1044 commodity_amount = 1;
1046 commodity_type = @"minerals";
1048 break;
1049
1050 case CARGO_THARGOID:
1051 commodity_amount = 1;
1053 commodity_type = @"alien_items";
1055 break;
1056
1058 commodity_amount = 1; // value > 0 is needed to be recognised as cargo by scripts;
1059 DESTROY(commodity_type); // will be defined elsewhere when needed.
1060 break;
1061
1062 case CARGO_RANDOM:
1063 // Could already be set by the cargo_carried key. If not, ensure at least one.
1064 if (commodity_amount == 0) commodity_amount = 1;
1065 break;
1066
1067 default:
1068 break;
1069 }
1070}
OOCargoType StringToCargoType(NSString *string) PURE_FUNC
@ CARGO_THARGOID
Definition OOTypes.h:74
@ CARGO_SLAVES
Definition OOTypes.h:71
@ CARGO_ALLOY
Definition OOTypes.h:72
@ CARGO_MINERALS
Definition OOTypes.h:73

◆ setUpEscorts

- (void) setUpEscorts

Definition at line 14942 of file ShipEntity.m.

1692{
1693 // Ensure that we do not try to create escorts if we are an escort ship ourselves.
1694 // This could lead to circular reference memory overflows (e.g. "boa-mk2" trying to create 4 "boa-mk2"
1695 // escorts or the case of two ships specifying eachother as escorts) - Nikos 20090510
1696 if ([self isEscort])
1697 {
1698 OOLogWARN(@"ship.setUp.escortShipCircularReference",
1699 @"Ship %@ requested escorts, when it is an escort ship itself. Avoiding possible circular reference overflow by ignoring escort setup.", self);
1700 return;
1701 }
1702
1703 if ([shipinfoDictionary objectForKey:@"escort_roles"] != nil)
1704 {
1705 [self setUpMixedEscorts];
1706 return;
1707 }
1708
1709 NSString *defaultRole = @"escort";
1710 NSString *escortRole = nil;
1711 NSString *escortShipKey = nil;
1712
1713 if (_pendingEscortCount == 0) return;
1714
1716 {
1717 if ([self hasPrimaryRole:@"police"] || [self hasPrimaryRole:@"hunter"])
1718 {
1719 _maxEscortCount = MAX_ESCORTS; // police and hunters get up to MAX_ESCORTS, overriding the 'escorts' key.
1720 [self updateEscortFormation];
1721 }
1722 else
1723 {
1724 _pendingEscortCount = _maxEscortCount; // other ships can only get what's defined inside their 'escorts' key.
1725 }
1726 }
1727
1728 if ([self isPolice]) defaultRole = @"wingman";
1729
1730 escortRole = [shipinfoDictionary oo_stringForKey:@"escort_role" defaultValue:nil];
1731 if (escortRole == nil)
1732 escortRole = [shipinfoDictionary oo_stringForKey:@"escort-role" defaultValue:defaultRole];
1733 if (![escortRole isEqualToString: defaultRole])
1734 {
1735 if (![[UNIVERSE newShipWithRole:escortRole] autorelease])
1736 {
1737 escortRole = defaultRole;
1738 }
1739 }
1740
1741 escortShipKey = [shipinfoDictionary oo_stringForKey:@"escort_ship" defaultValue:nil];
1742 if (escortShipKey == nil)
1743 escortShipKey = [shipinfoDictionary oo_stringForKey:@"escort-ship"];
1744
1745 if (escortShipKey != nil)
1746 {
1747 if (![[UNIVERSE newShipWithName:escortShipKey] autorelease])
1748 {
1749 escortShipKey = nil;
1750 }
1751 else
1752 {
1753 escortRole = [NSString stringWithFormat:@"[%@]",escortShipKey];
1754 }
1755 }
1756
1757 OOShipGroup *escortGroup = [self escortGroup];
1758 if ([self group] == nil)
1759 {
1760 [self setGroup:escortGroup]; // should probably become a copy of the escortGroup post NMSR.
1761 }
1762 [escortGroup setLeader:self];
1763
1764 [self refreshEscortPositions];
1765
1766 uint8_t currentEscortCount = [escortGroup count] - 1; // always at least 0.
1767
1768 while (_pendingEscortCount > 0 && ([self isThargoid] || currentEscortCount < _maxEscortCount))
1769 {
1770 // The following line adds escort 1 in position 1, etc... up to MAX_ESCORTS.
1771 HPVector ex_pos = [self coordinatesForEscortPosition:currentEscortCount];
1772
1773 ShipEntity *escorter = nil;
1774
1775 escorter = [UNIVERSE newShipWithRole:escortRole]; // retained
1776
1777 if (escorter == nil) break;
1778 [self setUpOneEscort:escorter inGroup:escortGroup withRole:escortRole atPosition:ex_pos andCount:currentEscortCount];
1779
1780 [escorter release];
1781
1783 currentEscortCount = [escortGroup count] - 1;
1784 }
1785 // done assigning escorts
1787}

◆ setUpFromDictionary:

- (BOOL) setUpFromDictionary: (NSDictionary *)  shipDict

Definition at line 14942 of file ShipEntity.m.

240 :(NSDictionary *) shipDict
241{
243
244 // Settings shared by players & NPCs.
245 //
246 // In order for default values to work and float values to not be junk,
247 // replace nil with empty dictionary. -- Ahruman 2008-04-28
248 shipinfoDictionary = [shipDict copy];
249 if (shipinfoDictionary == nil) shipinfoDictionary = [[NSDictionary alloc] init];
250 shipDict = shipinfoDictionary; // Ensure no mutation.
251
252 // set these flags explicitly.
254 haveStartedJSAI = NO;
255 scripted_misjump = NO;
257 being_fined = NO;
260 isMissile = NO;
262 _lightsActive = YES;
263
264
265 // set things from dictionary from here out - default values might require adjustment -- Kaks 20091130
266 _scaleFactor = [shipDict oo_floatForKey:@"model_scale_factor" defaultValue:1.0f];
267
268
269 float defaultSpeed = isStation ? 0.0f : 160.0f;
270 maxFlightSpeed = [shipDict oo_floatForKey:@"max_flight_speed" defaultValue:defaultSpeed];
271 max_flight_roll = [shipDict oo_floatForKey:@"max_flight_roll" defaultValue:2.0f];
272 max_flight_pitch = [shipDict oo_floatForKey:@"max_flight_pitch" defaultValue:1.0f];
273 max_flight_yaw = [shipDict oo_floatForKey:@"max_flight_yaw" defaultValue:max_flight_pitch]; // Note by default yaw == pitch
275
276 max_thrust = [shipDict oo_floatForKey:@"thrust" defaultValue:15.0f];
278
279 afterburner_rate = [shipDict oo_floatForKey:@"injector_burn_rate" defaultValue:AFTERBURNER_BURNRATE];
280 afterburner_speed_factor = [shipDict oo_floatForKey:@"injector_speed_factor" defaultValue:7.0f];
281 if (afterburner_speed_factor < 1.0)
282 {
283 OOLog(@"ship.setup.injectorSpeed",@"injector_speed_factor cannot be lower than 1.0 for %@",self);
285 }
286#if OO_VARIABLE_TORUS_SPEED
288 {
289 OOLog(@"ship.setup.injectorSpeed",@"injector_speed_factor cannot be higher than minimum torus speed factor (%f) for %@.",MIN_HYPERSPEED_FACTOR,self);
291 }
292#else
294 {
295 OOLog(@"ship.setup.injectorSpeed",@"injector_speed_factor cannot be higher than torus speed factor (%f) for %@.",HYPERSPEED_FACTOR,self);
297 }
298#endif
299
300 maxEnergy = [shipDict oo_floatForKey:@"max_energy" defaultValue:200.0f];
301 energy_recharge_rate = [shipDict oo_floatForKey:@"energy_recharge_rate" defaultValue:1.0f];
302
303 _showDamage = [shipDict oo_boolForKey:@"show_damage" defaultValue:(energy_recharge_rate > 0)];
304 // Each new ship should start in seemingly good operating condition, unless specifically told not to - this does not affect the ship's energy levels
305 [self setThrowSparks:[shipDict oo_boolForKey:@"throw_sparks" defaultValue:NO]];
306
307 weapon_facings = [shipDict oo_intForKey:@"weapon_facings" defaultValue:VALID_WEAPON_FACINGS] & VALID_WEAPON_FACINGS;
309 forward_weapon_type = OOWeaponTypeFromString([shipDict oo_stringForKey:@"forward_weapon_type" defaultValue:@"EQ_WEAPON_NONE"]);
311 aft_weapon_type = OOWeaponTypeFromString([shipDict oo_stringForKey:@"aft_weapon_type" defaultValue:@"EQ_WEAPON_NONE"]);
313 port_weapon_type = OOWeaponTypeFromString([shipDict oo_stringForKey:@"port_weapon_type" defaultValue:@"EQ_WEAPON_NONE"]);
315 starboard_weapon_type = OOWeaponTypeFromString([shipDict oo_stringForKey:@"starboard_weapon_type" defaultValue:@"EQ_WEAPON_NONE"]);
316
319 cloakPassive = [shipDict oo_boolForKey:@"cloak_passive" defaultValue:YES]; // Nikos - switched passive cloak default to YES 20120523
320 cloakAutomatic = [shipDict oo_boolForKey:@"cloak_automatic" defaultValue:YES];
321
322 missiles = [shipDict oo_intForKey:@"missiles" defaultValue:0];
323 /* TODO: The following initializes the missile list to be blank, which prevents a crash caused by hasOneEquipmentItem trying to access a missile list
324 previously initialized but then released. See issue #204. We need to investigate further the cause of the missile list being released.
325 - kanthoney 10/03/2017
326 Update 20170818: The issue seems to have been resolved properly using the fix below and the problem was apparently an access of the
327 missile_list array elements before their initialization and while we were checking whether equipment can be added or not. There is
328 probably not much more that can be done here, unless someone would like to have a go at refactoring the entire ship initialization
329 code. In any case, the crash is no more and the applied solution is both simple and logical - Nikos
330 */
331 unsigned i;
332 for (i = 0; i < missiles; i++)
333 {
334 missile_list[i] = nil;
335 }
336 max_missiles = [shipDict oo_intForKey:@"max_missiles" defaultValue:missiles];
339 missile_load_time = fmax(0.0, [shipDict oo_doubleForKey:@"missile_load_time" defaultValue:0.0]); // no negative load times
340 missile_launch_time = [UNIVERSE getTime] + missile_load_time;
341
342 // upgrades:
343 equipment_weight = 0;
344 if ([shipDict oo_fuzzyBooleanForKey:@"has_ecm"]) [self addEquipmentItem:@"EQ_ECM" inContext:@"npc"];
345 if ([shipDict oo_fuzzyBooleanForKey:@"has_scoop"]) [self addEquipmentItem:@"EQ_FUEL_SCOOPS" inContext:@"npc"];
346 if ([shipDict oo_fuzzyBooleanForKey:@"has_escape_pod"]) [self addEquipmentItem:@"EQ_ESCAPE_POD" inContext:@"npc"];
347 if ([shipDict oo_fuzzyBooleanForKey:@"has_cloaking_device"]) [self addEquipmentItem:@"EQ_CLOAKING_DEVICE" inContext:@"npc"];
348 if ([shipDict oo_floatForKey:@"has_energy_bomb"] > 0)
349 {
350 /* NOTE: has_energy_bomb actually refers to QC mines.
351
352 max_missiles for NPCs is a newish addition, and ships have
353 traditionally not needed to reserve a slot for a Q-mine added this
354 way. If has_energy_bomb is possible, and max_missiles is not
355 explicit, we add an extra missile slot to compensate.
356 -- Ahruman 2011-03-25
357 */
358 if ([shipDict oo_fuzzyBooleanForKey:@"has_energy_bomb"])
359 {
360 if (max_missiles == missiles && max_missiles < SHIPENTITY_MAX_MISSILES && [shipDict objectForKey:@"max_missiles"] == nil)
361 {
362 max_missiles++;
363 }
364 [self addEquipmentItem:@"EQ_QC_MINE" inContext:@"npc"];
365 }
366 }
367
368 if ([shipDict oo_fuzzyBooleanForKey:@"has_fuel_injection"]) [self addEquipmentItem:@"EQ_FUEL_INJECTION" inContext:@"npc"];
369
370#if USEMASC
371 if ([shipDict oo_fuzzyBooleanForKey:@"has_military_jammer"]) [self addEquipmentItem:@"EQ_MILITARY_JAMMER" inContext:@"npc"];
372 if ([shipDict oo_fuzzyBooleanForKey:@"has_military_scanner_filter"]) [self addEquipmentItem:@"EQ_MILITARY_SCANNER_FILTER" inContext:@"npc"];
373#endif
374
375
376 // can it be 'mined' for alloys?
377 canFragment = [shipDict oo_fuzzyBooleanForKey:@"fragment_chance" defaultValue:0.9];
378 isWreckage = NO;
379
380 // can subentities be destroyed separately?
381 isFrangible = [shipDict oo_boolForKey:@"frangible" defaultValue:YES];
382
383 max_cargo = [shipDict oo_unsignedIntForKey:@"max_cargo"];
384 extra_cargo = [shipDict oo_unsignedIntForKey:@"extra_cargo" defaultValue:15];
385
386 hyperspaceMotorSpinTime = [shipDict oo_floatForKey:@"hyperspace_motor_spin_time" defaultValue:DEFAULT_HYPERSPACE_SPIN_TIME];
387 if(![shipDict oo_boolForKey:@"hyperspace_motor" defaultValue:YES]) hyperspaceMotorSpinTime = -1;
388
389 [name autorelease];
390 name = [[shipDict oo_stringForKey:@"name" defaultValue:@"?"] copy];
391
392 [shipUniqueName autorelease];
393 shipUniqueName = [[shipDict oo_stringForKey:@"ship_name" defaultValue:@""] copy];
394
395 [shipClassName autorelease];
396 shipClassName = [[shipDict oo_stringForKey:@"ship_class_name" defaultValue:name] copy];
397
398 [displayName autorelease];
399 displayName = [[shipDict oo_stringForKey:@"display_name" defaultValue:nil] copy];
400
401 // Load the model (must be before subentities)
402 NSString *modelName = [shipDict oo_stringForKey:@"model"];
403 if (modelName != nil)
404 {
405 OOMesh *mesh = nil;
406
407 mesh = [OOMesh meshWithName:modelName
408 cacheKey:[NSString stringWithFormat:@"%@-%.3f",_shipKey,_scaleFactor]
409 materialDictionary:[shipDict oo_dictionaryForKey:@"materials"]
410 shadersDictionary:[shipDict oo_dictionaryForKey:@"shaders"]
411 smooth:[shipDict oo_boolForKey:@"smooth" defaultValue:NO]
412 shaderMacros:OODefaultShipShaderMacros()
414 scaleFactor:_scaleFactor
415 cacheWriteable:YES];
416
417 if (mesh == nil) return NO;
418 [self setMesh:mesh];
419 }
420
421 float density = [shipDict oo_floatForKey:@"density" defaultValue:1.0f];
422 if (octree) mass = (GLfloat)(density * 20.0f * [octree volume]);
423
425 default_laser_color = [[OOColor brightColorWithDescription:[shipDict objectForKey:@"laser_color"]] retain];
426
427 if (default_laser_color == nil)
428 {
429 [self setLaserColor:[OOColor redColor]];
430 }
431 else
432 {
433 [self setLaserColor:default_laser_color];
434 }
435 // exhaust emissive color
436 OORGBAComponents defaultExhaustEmissiveColorComponents; // pale blue is exhaust default color
437 defaultExhaustEmissiveColorComponents.r = 0.7f;
438 defaultExhaustEmissiveColorComponents.g = 0.9f;
439 defaultExhaustEmissiveColorComponents.b = 1.0f;
440 defaultExhaustEmissiveColorComponents.a = 0.9f;
441 OOColor *color = [OOColor brightColorWithDescription:[shipDict objectForKey:@"exhaust_emissive_color"]];
442 if (color == nil) color = [OOColor colorWithRGBAComponents:defaultExhaustEmissiveColorComponents];
443 [self setExhaustEmissiveColor:color];
444
445 [self clearSubEntities];
446 [self setUpSubEntities];
447
448// correctly initialise weaponRange, etc. (must be after subentity setup)
450 {
451 OOWeaponType weapon_type = nil;
452 BOOL hasTurrets = NO;
453 NSEnumerator *subEnum = [self shipSubEntityEnumerator];
454 ShipEntity *se = nil;
455 while (isWeaponNone(weapon_type) && (se = [subEnum nextObject]))
456 {
457 weapon_type = se->forward_weapon_type;
458 if (se->behaviour == BEHAVIOUR_TRACK_AS_TURRET)
459 {
460 hasTurrets = YES;
461 }
462 }
463 if (isWeaponNone(weapon_type) && hasTurrets)
464 { /* safety for ships only equipped with turrets
465 note: this was hard-coded to 10000.0, although turrets have a notably
466 shorter range. We are using a multiplier of 1.667 in order to not change
467 something that already works, but probably it would be best to use
468 TURRET_SHOT_RANGE * COMBAT_WEAPON_RANGE_FACTOR here
469 */
471 }
472 else
473 {
474 [self setWeaponDataFromType:weapon_type];
475 }
476 }
477 else
478 {
479 [self setWeaponDataFromType:forward_weapon_type];
480 }
481
482 // rotating subentities
484 if ([shipDict objectForKey:@"rotational_velocity"])
485 {
486 subentityRotationalVelocity = [shipDict oo_quaternionForKey:@"rotational_velocity"];
487 }
488
489 // set weapon offsets
490 NSString *weaponMountMode = [shipDict oo_stringForKey:@"weapon_mount_mode" defaultValue:@"single"];
491 _multiplyWeapons = [weaponMountMode isEqualToString:@"multiply"];
492 forwardWeaponOffset = [[self getWeaponOffsetFrom:shipDict withKey:@"weapon_position_forward" inMode:weaponMountMode] retain];
493 aftWeaponOffset = [[self getWeaponOffsetFrom:shipDict withKey:@"weapon_position_aft" inMode:weaponMountMode] retain];
494 portWeaponOffset = [[self getWeaponOffsetFrom:shipDict withKey:@"weapon_position_port" inMode:weaponMountMode] retain];
495 starboardWeaponOffset = [[self getWeaponOffsetFrom:shipDict withKey:@"weapon_position_starboard" inMode:weaponMountMode] retain];
496
497
498 tractor_position = vector_multiply_scalar([shipDict oo_vectorForKey:@"scoop_position"],_scaleFactor);
499
500
501
502 // sun glare filter - default is high filter, both for HDR and SDR
503 [self setSunGlareFilter:[shipDict oo_floatForKey:@"sun_glare_filter" defaultValue:0.97f]];
504
505 // Get scriptInfo dictionary, containing arbitrary stuff scripts might be interested in.
506 scriptInfo = [[shipDict oo_dictionaryForKey:@"script_info" defaultValue:nil] retain];
507
508 explosionType = [[shipDict oo_arrayForKey:@"explosion_type" defaultValue:nil] retain];
509
510 isDemoShip = NO;
511
512 return YES;
513
515}
#define VALID_WEAPON_FACINGS
Definition OOTypes.h:239
#define HYPERSPEED_FACTOR
#define SHIPENTITY_MAX_MISSILES
Definition ShipEntity.h:77
OOWeaponType OOWeaponTypeFromString(NSString *string) PURE_FUNC
OOColor * colorWithRGBAComponents:(OORGBAComponents components)
Definition OOColor.m:109
OOColor * brightColorWithDescription:(id description)
Definition OOColor.m:205
OOColor * redColor()
Definition OOColor.m:268
OOWeaponFacingSet weapon_facings
Definition ShipEntity.h:304
unsigned haveStartedJSAI
Definition ShipEntity.h:280
unsigned _showDamage
Definition ShipEntity.h:270
unsigned haveExecutedSpawnAction
Definition ShipEntity.h:279

◆ setUpMixedEscorts

- (void) setUpMixedEscorts
implementation

Provided by category ShipEntity(Private).

Definition at line 14942 of file ShipEntity.m.

1791{
1792 NSArray *escortRoles = [shipinfoDictionary oo_arrayForKey:@"escort_roles" defaultValue:nil];
1793 if (escortRoles == nil)
1794 {
1795 OOLogWARN(@"eship.setUp.escortShipRoles",
1796 @"Ship %@ has bad escort_roles definition.", self);
1797 return;
1798 }
1799 NSDictionary *escortDefinition = nil;
1800 NSDictionary *systeminfo = nil;
1801 OOGovernmentID government;
1802
1803 systeminfo = [UNIVERSE currentSystemData];
1804 government = [systeminfo oo_unsignedCharForKey:KEY_GOVERNMENT];
1805
1806 OOShipGroup *escortGroup = [self escortGroup];
1807 if ([self group] == nil)
1808 {
1809 [self setGroup:escortGroup]; // should probably become a copy of the escortGroup post NMSR.
1810 }
1811 [escortGroup setLeader:self];
1813 [self refreshEscortPositions];
1814
1815 uint8_t currentEscortCount = [escortGroup count] - 1; // always at least 0
1816
1817 _maxEscortCount = 0;
1818 int8_t i = 0;
1819 foreach (escortDefinition, escortRoles)
1820 {
1821 if (currentEscortCount >= MAX_ESCORTS)
1822 {
1823 break;
1824 }
1825 // int rather than uint because, at least for min, there is a
1826 // use to giving a negative value
1827 int8_t min = [escortDefinition oo_intForKey:@"min" defaultValue:0];
1828 int8_t max = [escortDefinition oo_intForKey:@"max" defaultValue:2];
1829 NSString *escortRole = [escortDefinition oo_stringForKey:@"role" defaultValue:@"escort"];
1830 int8_t desired = max;
1831 if (min < desired)
1832 {
1833 for (i = min ; i < max ; i++)
1834 {
1835 if (Ranrot()%11 < government+2)
1836 {
1837 desired--;
1838 }
1839 }
1840 }
1841 for (i = 0; i < desired; i++)
1842 {
1843 if (currentEscortCount >= MAX_ESCORTS)
1844 {
1845 break;
1846 }
1847 if (![escortRole isEqualToString:@""])
1848 {
1849 HPVector ex_pos = [self coordinatesForEscortPosition:currentEscortCount];
1850 ShipEntity *escorter = [UNIVERSE newShipWithRole:escortRole]; // retained
1851 if (escorter == nil)
1852 {
1853 break;
1854 }
1855 [self setUpOneEscort:escorter inGroup:escortGroup withRole:escortRole atPosition:ex_pos andCount:currentEscortCount];
1856 [escorter release];
1857 }
1858 currentEscortCount++;
1860 }
1861 }
1862 // done assigning escorts
1864}
uint8_t OOGovernmentID
Definition OOTypes.h:206

◆ setUpOneEscort:inGroup:withRole:atPosition:andCount:

- (void) setUpOneEscort: (ShipEntity *)  escorter
inGroup: (OOShipGroup *)  escortGroup
withRole: (NSString *)  escortRole
atPosition: (HPVector)  ex_pos
andCount: (uint8_t)  currentEscortCount 
implementation

Provided by category ShipEntity(Private).

Definition at line 14942 of file ShipEntity.m.

1867 :(ShipEntity *)escorter inGroup:(OOShipGroup *)escortGroup withRole:(NSString *)escortRole atPosition:(HPVector)ex_pos andCount:(uint8_t)currentEscortCount
1868{
1869 NSString *autoAI = nil;
1870 NSString *pilotRole = nil;
1871 NSDictionary *autoAIMap = nil;
1872 NSDictionary *escortShipDict = nil;
1873 AI *escortAI = nil;
1874 NSString *defaultRole = @"escort";
1875
1876 if ([self isPolice])
1877 {
1878 defaultRole = @"wingman";
1879 pilotRole = @"police"; // police are always insured.
1880 }
1881 else
1882 {
1883 pilotRole = bounty ? @"pirate" : @"hunter"; // hunters have insurancies, pirates not.
1884 }
1885
1886 double dd = escorter->collision_radius;
1887
1888 if (EXPECT(currentEscortCount < (uint8_t)MAX_ESCORTS))
1889 {
1890 // spread them around a little randomly
1891 ex_pos.x += dd * 6.0 * (randf() - 0.5);
1892 ex_pos.y += dd * 6.0 * (randf() - 0.5);
1893 ex_pos.z += dd * 6.0 * (randf() - 0.5);
1894 }
1895 else
1896 {
1897 // Thargoid armada(!) Add more distance between the 'escorts'.
1898 ex_pos.x += dd * 12.0 * (randf() - 0.5);
1899 ex_pos.y += dd * 12.0 * (randf() - 0.5);
1900 ex_pos.z += dd * 12.0 * (randf() - 0.5);
1901 }
1902
1903 [escorter setPosition:ex_pos]; // minimise lollipop flash
1904
1905 if ([escorter crew] == nil)
1906 {
1907 [escorter setSingleCrewWithRole:pilotRole];
1908 }
1909
1910 [escorter setPrimaryRole:defaultRole]; //for mothership
1911 // in case this hasn't yet been set, make sure escorts get a real scan class
1912 // shouldn't happen very often, but is possible
1913 if (scanClass == CLASS_NOT_SET)
1914 {
1915 scanClass = CLASS_NEUTRAL;
1916 }
1917 [escorter setScanClass:scanClass]; // you are the same as I
1918
1919 if ([self bounty] == 0) [escorter setBounty:0 withReason:kOOLegalStatusReasonSetup]; // Avoid dirty escorts for clean mothers
1920
1921 // find the right autoAI.
1922 escortShipDict = [escorter shipInfoDictionary];
1923 autoAIMap = [ResourceManager dictionaryFromFilesNamed:@"autoAImap.plist" inFolder:@"Config" andMerge:YES];
1924 autoAI = [autoAIMap oo_stringForKey:defaultRole];
1925 if (autoAI==nil) // no 'wingman' defined in autoAImap?
1926 {
1927 autoAI = [autoAIMap oo_stringForKey:@"escort" defaultValue:@"nullAI.plist"];
1928 }
1929
1930 escortAI = [escorter getAI];
1931
1932 // Let the populator decide which AI to use, unless we have a working alternative AI & we specify auto_ai = NO !
1933 if ( (escortRole && [escortShipDict oo_fuzzyBooleanForKey:@"auto_ai" defaultValue:YES])
1934 || ([[escortAI name] isEqualToString: @"nullAI.plist"] && ![autoAI isEqualToString:@"nullAI.plist"]) )
1935 {
1936 [escorter switchAITo:autoAI];
1937 }
1938
1939 [escorter setGroup:escortGroup];
1940 [escorter setOwner:self]; // mark self as group leader
1941
1942
1943 if ([self status] == STATUS_DOCKED)
1944 {
1945 [[self owner] addShipToLaunchQueue:escorter withPriority:NO];
1946 }
1947 else
1948 {
1949 [UNIVERSE addEntity:escorter]; // STATUS_IN_FLIGHT, AI state GLOBAL
1950 [escortAI setState:@"FLYING_ESCORT"]; // Begin escort flight. (If the AI doesn't define FLYING_ESCORT, this has no effect.)
1951 [escorter doScriptEvent:OOJSID("spawnedAsEscort") withArgument:self];
1952 }
1953
1954 if([escorter heatInsulation] < [self heatInsulation]) [escorter setHeatInsulation:[self heatInsulation]]; // give escorts same protection as mother.
1955 if(([escorter maxFlightSpeed] < cruiseSpeed) && ([escorter maxFlightSpeed] > cruiseSpeed * 0.3))
1956 cruiseSpeed = [escorter maxFlightSpeed] * 0.99; // adapt patrolSpeed to the slowest escort but ignore the very slow ones.
1957
1958
1959 if (bounty)
1960 {
1961 int extra = 1 | (ranrot_rand() & 15);
1962 // if mothership is offender, make sure escorter is too.
1963 [escorter markAsOffender:extra withReason:kOOLegalStatusReasonSetup];
1964 }
1965 else
1966 {
1967 // otherwise force the escort to be clean
1968 [escorter setBounty:0 withReason:kOOLegalStatusReasonSetup];
1969 }
1970
1971}
void setState:(NSString *stateName)
Definition AI.m:334
NSDictionary * dictionaryFromFilesNamed:inFolder:andMerge:(NSString *fileName,[inFolder] NSString *folderName,[andMerge] BOOL mergeFiles)
void setSingleCrewWithRole:(NSString *crewRole)
void setPrimaryRole:(NSString *role)
void setHeatInsulation:(GLfloat value)

◆ setUpOneFlasher:

- (BOOL) setUpOneFlasher: (NSDictionary *)  subentDict
implementation

Provided by category ShipEntity(Private).

Definition at line 14942 of file ShipEntity.m.

926 :(NSDictionary *) subentDict
927{
929 [flasher setPosition:HPvector_multiply_scalar([subentDict oo_hpvectorForKey:@"position"],_scaleFactor)];
930 [flasher rescaleBy:_scaleFactor];
931 [self addSubEntity:flasher];
932 return YES;
933}
instancetype flasherWithDictionary:(NSDictionary *dictionary)
void rescaleBy:(GLfloat factor)

◆ setUpOneStandardSubentity:asTurret:

- (BOOL) setUpOneStandardSubentity: (NSDictionary *)  subentDict
asTurret: (BOOL)  asTurret 

Definition at line 14942 of file ShipEntity.m.

936 :(NSDictionary *)subentDict asTurret:(BOOL)asTurret
937{
938 ShipEntity *subentity = nil;
939 NSString *subentKey = nil;
940 HPVector subPosition;
941 Quaternion subOrientation;
942
943 subentKey = [subentDict oo_stringForKey:@"subentity_key"];
944 if (subentKey == nil) {
945 OOLog(@"setup.ship.badEntry.subentities",@"Failed to set up entity - no subentKey in %@",subentDict);
946 return NO;
947 }
948
949 if (!asTurret && [self isStation] && [subentDict oo_boolForKey:@"is_dock"])
950 {
951 subentity = [UNIVERSE newDockWithName:subentKey andScaleFactor:_scaleFactor];
952 }
953 else
954 {
955 subentity = [UNIVERSE newSubentityWithName:subentKey andScaleFactor:_scaleFactor];
956 }
957 if (subentity == nil) {
958 OOLog(@"setup.ship.badEntry.subentities",@"Failed to set up entity %@",subentKey);
959 return NO;
960 }
961
962 subPosition = HPvector_multiply_scalar([subentDict oo_hpvectorForKey:@"position"],_scaleFactor);
963 subOrientation = [subentDict oo_quaternionForKey:@"orientation"];
964
965 [subentity setPosition:subPosition];
966 [subentity setOrientation:subOrientation];
967 [subentity setReference:vector_forward_from_quaternion(subOrientation)];
968 // subentities inherit parent personality
969 [subentity setEntityPersonalityInt:[self entityPersonalityInt]];
970
971 if (asTurret)
972 {
973 [subentity setBehaviour:BEHAVIOUR_TRACK_AS_TURRET];
974 [subentity setWeaponRechargeRate:[subentDict oo_floatForKey:@"fire_rate" defaultValue:TURRET_SHOT_FREQUENCY]];
975 [subentity setWeaponEnergy:[subentDict oo_floatForKey:@"weapon_energy" defaultValue:TURRET_TYPICAL_ENERGY]];
976 [subentity setWeaponRange:[subentDict oo_floatForKey:@"weapon_range" defaultValue:TURRET_SHOT_RANGE]];
977 [subentity setStatus: STATUS_ACTIVE];
978 }
979 else
980 {
981 [subentity setStatus:STATUS_INACTIVE];
982 }
983
984 [subentity overrideScriptInfo:[subentDict oo_dictionaryForKey:@"script_info"]];
985
986 [self addSubEntity:subentity];
987 [subentity setSubIdx:_maxShipSubIdx];
989
990 // update subentities
991 BoundingBox sebb = [subentity findSubentityBoundingBox];
992 bounding_box_add_vector(&totalBoundingBox, sebb.max);
993 bounding_box_add_vector(&totalBoundingBox, sebb.min);
994
995 if (!asTurret && [self isStation] && [subentDict oo_boolForKey:@"is_dock"])
996 {
997 BOOL allow_docking = [subentDict oo_boolForKey:@"allow_docking" defaultValue:YES];
998 BOOL ddc = [subentDict oo_boolForKey:@"disallowed_docking_collides" defaultValue:NO];
999 BOOL allow_launching = [subentDict oo_boolForKey:@"allow_launching" defaultValue:YES];
1000 // do not include this key in OOShipRegistry; should never be set by shipdata
1001 BOOL virtual_dock = [subentDict oo_boolForKey:@"_is_virtual_dock" defaultValue:NO];
1002 if (virtual_dock)
1003 {
1004 [(DockEntity *)subentity setVirtual];
1005 }
1006
1007 [(DockEntity *)subentity setDimensionsAndCorridor:allow_docking:ddc:allow_launching];
1008 [subentity setDisplayName:[subentDict oo_stringForKey:@"dock_label" defaultValue:@"the docking bay"]];
1009 }
1010
1011 [subentity release];
1012
1013 return YES;
1014}
void setWeaponEnergy:(float value)
void setDisplayName:(NSString *inName)
void setWeaponRange:(GLfloat value)
void setWeaponRechargeRate:(float value)
void setEntityPersonalityInt:(uint16_t value)
void setSubIdx:(NSUInteger value)
Definition ShipEntity.m:780
void overrideScriptInfo:(NSDictionary *override)
BoundingBox findSubentityBoundingBox()
void setReference:(Vector v)

◆ setUpOneSubentity:

- (BOOL) setUpOneSubentity: (NSDictionary *)  subentDict
implementation

Provided by category ShipEntity(Private).

Definition at line 14942 of file ShipEntity.m.

906 :(NSDictionary *) subentDict
907{
909
910 NSString *type = nil;
911
912 type = [subentDict oo_stringForKey:@"type"];
913 if ([type isEqualToString:@"flasher"])
914 {
915 return [self setUpOneFlasher:subentDict];
916 }
917 else
918 {
919 return [self setUpOneStandardSubentity:subentDict asTurret:[type isEqualToString:@"ball_turret"]];
920 }
921
923}

◆ setUpShipFromDictionary:

- (BOOL) setUpShipFromDictionary: (NSDictionary *)  shipDict

Reimplemented in DockEntity, StationEntity, and PlayerEntity.

Definition at line 14942 of file ShipEntity.m.

519 :(NSDictionary *) shipDict
520{
522
523 if (![self setUpFromDictionary:shipDict]) return NO;
524
525 // NPC-only settings.
526 //
532 reference = v_forward; // reference vector for (* turrets *)
533
534 isShip = YES;
535
536 // scan class settings. 'scanClass' is in common usage, but we could also have a more standard 'scan_class' key with higher precedence. Kaks 20090810
537 // let's see if scan_class is set...
538 scanClass = OOScanClassFromString([shipDict oo_stringForKey:@"scan_class" defaultValue:@"CLASS_NOT_SET"]);
539
540 // if not, try 'scanClass'. NOTE: non-standard capitalization is documented and entrenched.
541 if (scanClass == CLASS_NOT_SET)
542 {
543 scanClass = OOScanClassFromString([shipDict oo_stringForKey:@"scanClass" defaultValue:@"CLASS_NOT_SET"]);
544 }
545
546 [scan_description autorelease];
547 scan_description = [[shipDict oo_stringForKey:@"scan_description" defaultValue:nil] copy];
548
549 // FIXME: give NPCs shields instead.
550
551 if ([shipDict oo_fuzzyBooleanForKey:@"has_shield_booster"]) [self addEquipmentItem:@"EQ_SHIELD_BOOSTER" inContext:@"npc"];
552 if ([shipDict oo_fuzzyBooleanForKey:@"has_shield_enhancer"]) [self addEquipmentItem:@"EQ_SHIELD_ENHANCER" inContext:@"npc"];
553
554 // Start with full energy banks.
556 weapon_temp = 0.0f;
557 forward_weapon_temp = 0.0f;
558 aft_weapon_temp = 0.0f;
559 port_weapon_temp = 0.0f;
561
562 // setWeaponDataFromType inside setUpFromDictionary should set weapon_damage from the front laser.
563 // no weapon_damage? It's a missile: set weapon_damage from shipdata!
564 if (weapon_damage == 0.0)
565 {
566 weapon_damage_override = weapon_damage = [shipDict oo_floatForKey:@"weapon_energy" defaultValue:0]; // any damage value for missiles/bombs
567 }
568 else
569 {
571 }
572
573 scannerRange = [shipDict oo_floatForKey:@"scanner_range" defaultValue:(float)SCANNER_MAX_RANGE];
574
575 fuel = [shipDict oo_unsignedShortForKey:@"fuel"]; // Does it make sense that this defaults to 0? Should it not be 70? -- Ahruman
576
577 fuel_accumulator = 1.0;
578
579 [self setBounty:[shipDict oo_unsignedIntForKey:@"bounty" defaultValue:0] withReason:kOOLegalStatusReasonSetup];
580
581 [shipAI autorelease];
582 shipAI = [[AI alloc] init];
583 [shipAI setOwner:self];
584 [self setAITo:[shipDict oo_stringForKey:@"ai_type" defaultValue:@"nullAI.plist"]];
585
586 likely_cargo = [shipDict oo_unsignedIntForKey:@"likely_cargo"];
587 noRocks = [shipDict oo_fuzzyBooleanForKey:@"no_boulders"];
588
591 NSString *cargoString = [shipDict oo_stringForKey:@"cargo_carried"];
592 if (cargoString != nil)
593 {
594 if ([cargoString isEqualToString:@"SCARCE_GOODS"])
595 {
597 }
598 else if ([cargoString isEqualToString:@"PLENTIFUL_GOODS"])
599 {
601 }
602 else
603 {
605
606 OOCommodityType c_commodity = nil;
607 int c_amount = 1;
608 NSScanner *scanner = [NSScanner scannerWithString:cargoString];
609 if ([scanner scanInt:&c_amount])
610 {
611 [scanner ooliteScanCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:NULL]; // skip whitespace
612 c_commodity = [[scanner string] substringFromIndex:[scanner scanLocation]];
613 if ([[UNIVERSE commodities] goodDefined:c_commodity])
614 {
615 [self setCommodityForPod:c_commodity andAmount:c_amount];
616 }
617 else
618 {
619 c_commodity = [[UNIVERSE commodities] goodNamed:c_commodity];
620 if ([[UNIVERSE commodities] goodDefined:c_commodity])
621 {
622 [self setCommodityForPod:c_commodity andAmount:c_amount];
623 }
624 }
625 }
626 else
627 {
628 c_amount = 1;
629 c_commodity = [shipDict oo_stringForKey:@"cargo_carried"];
630 if ([[UNIVERSE commodities] goodDefined:c_commodity])
631 {
632 [self setCommodityForPod:c_commodity andAmount:c_amount];
633 }
634 else
635 {
636 c_commodity = [[UNIVERSE commodities] goodNamed:c_commodity];
637 if ([[UNIVERSE commodities] goodDefined:c_commodity])
638 {
639 [self setCommodityForPod:c_commodity andAmount:c_amount];
640 }
641 }
642 }
643 }
644 }
645
646 cargoString = [shipDict oo_stringForKey:@"cargo_type"];
647 if (cargoString)
648 {
649 if (cargo != nil) [cargo autorelease];
650 cargo = [[NSMutableArray alloc] initWithCapacity:max_cargo]; // alloc retains;
651
652 [self setUpCargoType:cargoString];
653 }
654 else if (scanClass != CLASS_CARGO)
655 {
656 if (cargo != nil) [cargo autorelease];
657 cargo = [[NSMutableArray alloc] initWithCapacity:max_cargo]; // alloc retains;
658 // if not CLASS_CARGO, and no cargo type set, default to CARGO_NOT_CARGO
660 }
661
662 hasScoopMessage = [shipDict oo_boolForKey:@"has_scoop_message" defaultValue:YES];
663
664
665 [roleSet release];
666 roleSet = [[[OORoleSet roleSetWithString:[shipDict oo_stringForKey:@"roles"]] roleSetWithRemovedRole:@"player"] retain];
667 [primaryRole release];
669
670 [self setOwner:self];
671 [self setHulk:[shipDict oo_boolForKey:@"is_hulk"]];
672
673 // these are the colors used for the "lollipop" of the ship. Any of the two (or both, for flash effect) can be defined. nil means use default from shipData.
674 [self setScannerDisplayColor1:nil];
675 [self setScannerDisplayColor2:nil];
676 // and the same for the "hostile" colours
677 [self setScannerDisplayColorHostile1:nil];
678 [self setScannerDisplayColorHostile2:nil];
679
680
681 // Populate the missiles here. Must come after scanClass.
682 _missileRole = [shipDict oo_stringForKey:@"missile_role"];
683 unsigned i, j;
684 for (i = 0, j = 0; i < missiles; i++)
685 {
686 missile_list[i] = [self selectMissile];
687 // could loop forever (if missile_role is badly defined, selectMissile might return nil in some cases) . Try 3 times, and if no luck, skip
688 if (missile_list[i] == nil && j < 3)
689 {
690 j++;
691 i--;
692 }
693 else
694 {
695 j = 0;
696 if (missile_list[i] == nil)
697 {
698 missiles--;
699 }
700 }
701 }
702
703 // accuracy. Must come after scanClass, because we are using scanClass to determine if this is a missile.
704
705// missiles: range 0 to +10
706// ships: range -5 to +10, but randomly only -5 <= accuracy < +5
707// enables "better" AIs at +5 and above
708// police and military always have positive accuracy
709
710 accuracy = [shipDict oo_floatForKey:@"accuracy" defaultValue:-100.0f]; // Out-of-range default
711 if (accuracy < -5.0f || accuracy > 10.0f)
712 {
713 accuracy = (randf() * 10.0)-5.0;
714
715 if (accuracy < 0.0f && (scanClass == CLASS_MILITARY || scanClass == CLASS_POLICE))
716 { // police and military pilots have a better average skill.
718 }
719 }
720 if (scanClass == CLASS_MISSILE)
721 { // missile accuracy range is 0 to 10
722 accuracy = OOClamp_0_max_f(accuracy, 10.0f);
723 }
724 [self setAccuracy:accuracy]; // set derived variables
725 _missed_shots = 0;
726
727 // escorts
728 _maxEscortCount = MIN([shipDict oo_unsignedCharForKey:@"escorts" defaultValue:0], (uint8_t)MAX_ESCORTS);
730 if (_pendingEscortCount == 0 && [shipDict oo_arrayForKey:@"escort_roles" defaultValue:nil] != nil)
731 {
732 // mostly ignored by setUpMixedEscorts, but needs to be high
733 // enough that it doesn't end up at zero (e.g. by governmental
734 // reductions in [Universe addShipAt]
736 }
737
738
739 // beacons
740 [self setBeaconCode:[shipDict oo_stringForKey:@"beacon"]];
741 [self setBeaconLabel:[shipDict oo_stringForKey:@"beacon_label" defaultValue:[shipDict oo_stringForKey:@"beacon"]]];
742
743
744 // contact tracking entities
745 [self setTrackCloseContacts:[shipDict oo_boolForKey:@"track_contacts" defaultValue:NO]];
746
747 // ship skin insulation factor (1.0 is normal)
748 [self setHeatInsulation:[shipDict oo_floatForKey:@"heat_insulation" defaultValue:[self hasHeatShield] ? 2.0 : 1.0]];
749
750 // unpiloted (like missiles asteroids etc.)
751 _explicitlyUnpiloted = [shipDict oo_fuzzyBooleanForKey:@"unpiloted"];
753 {
754 [self setCrew:nil];
755 }
756 else
757 {
758 // crew and passengers
759 NSDictionary *cdict = [[UNIVERSE characters] objectForKey:[shipDict oo_stringForKey:@"pilot"]];
760 if (cdict != nil)
761 {
763 [self setCrew:[NSArray arrayWithObject:pilot]];
764 }
765 }
766
767 [self setShipScript:[shipDict oo_stringForKey:@"script"]];
768
769 home_system = [UNIVERSE currentSystemID];
770 destination_system = [UNIVERSE currentSystemID];
771
772 reactionTime = [shipDict oo_floatForKey: @"reaction_time" defaultValue: COMBAT_AI_STANDARD_REACTION_TIME];
773
774 return YES;
775
777}
OOScanClass OOScanClassFromString(NSString *string) PURE_FUNC
const OOMatrix kIdentityMatrix
Definition OOMatrix.m:31
OOCharacter * characterWithDictionary:(NSDictionary *c_dict)
instancetype roleSetWithString:(NSString *roleString)
Definition OORoleSet.m:44
unsigned hasScoopMessage
Definition ShipEntity.h:275
GLfloat weapon_damage_override
Definition ShipEntity.h:310

◆ setUpSubEntities

- (BOOL) setUpSubEntities

Reimplemented in StationEntity.

Definition at line 14942 of file ShipEntity.m.

856{
858
859 unsigned int i;
860 NSDictionary *shipDict = [self shipInfoDictionary];
861 NSArray *plumes = [shipDict oo_arrayForKey:@"exhaust"];
862
864 _maxShipSubIdx = 0;
865
866 for (i = 0; i < [plumes count]; i++)
867 {
868 NSArray *definition = ScanTokensFromString([plumes oo_stringAtIndex:i]);
869 OOExhaustPlumeEntity *exhaust = [OOExhaustPlumeEntity exhaustForShip:self withDefinition:definition andScale:_scaleFactor];
870 [self addSubEntity:exhaust];
871 }
872
873 NSArray *subs = [shipDict oo_arrayForKey:@"subentities"];
874
876
877 for (i = 0; i < [subs count]; i++)
878 {
879 [self setUpOneSubentity:[subs oo_dictionaryAtIndex:i]];
880 }
881
883
884 return YES;
885
887}
#define NO_DRAW_DISTANCE_FACTOR
Definition Entity.h:46
id exhaustForShip:withDefinition:andScale:(ShipEntity *ship,[withDefinition] NSArray *definition,[andScale] float scale)

Referenced by ShipRestoreSubEntities().

+ Here is the caller graph for this function:

◆ setWeaponDataFromType:

- (void) setWeaponDataFromType: (OOWeaponType weapon_type

Definition at line 7408 of file ShipEntity.m.

7479 : (OOWeaponType) weapon_type
7480{
7481 weaponRange = getWeaponRangeFromType(weapon_type);
7482 weapon_energy_use = [weapon_type weaponEnergyUse];
7485 weapon_damage = [weapon_type weaponDamage];
7486
7487 if (default_laser_color == nil)
7488 {
7489 OOColor *wcol = [weapon_type weaponColor];
7490 if (wcol != nil)
7491 {
7492 [self setLaserColor:wcol];
7493 }
7494 }
7495
7496}
GLfloat weaponShotTemperature()
OOColor * weaponColor()
GLfloat weaponRechargeRate()

◆ setWeaponEnergy:

- (void) setWeaponEnergy: (float)  value

Definition at line 7408 of file ShipEntity.m.

7523 :(float)value
7524{
7525 weapon_damage = value;
7526}

◆ setWeaponMount:toWeapon:

- (BOOL) setWeaponMount: (OOWeaponFacing facing
toWeapon: (NSString *)  eqKey 

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3492 :(OOWeaponFacing)facing toWeapon:(NSString *)eqKey
3493{
3494 // sets WEAPON_NONE if not recognised
3495 if (weapon_facings & facing)
3496 {
3498 switch (facing)
3499 {
3501 forward_weapon_type = chosen_weapon;
3502 break;
3503
3504 case WEAPON_FACING_AFT:
3505 aft_weapon_type = chosen_weapon;
3506 break;
3507
3508 case WEAPON_FACING_PORT:
3509 port_weapon_type = chosen_weapon;
3510 break;
3511
3513 starboard_weapon_type = chosen_weapon;
3514 break;
3515
3516 case WEAPON_FACING_NONE:
3517 break;
3518 }
3519
3520 return YES;
3521 }
3522 else
3523 {
3524 return NO;
3525 }
3526}

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ setWeaponRange:

- (void) setWeaponRange: (GLfloat)  value

Definition at line 7408 of file ShipEntity.m.

7473 : (GLfloat) value
7474{
7475 weaponRange = value;
7476}

◆ setWeaponRechargeRate:

- (void) setWeaponRechargeRate: (float)  value

Definition at line 7408 of file ShipEntity.m.

7517 :(float)value
7518{
7519 weapon_recharge_rate = value;
7520}

◆ setYaw:

- (void) setYaw: (double)  amount

Definition at line 7616 of file ShipEntity.m.

8225 :(double) amount
8226{
8227 flightYaw = amount * M_PI / 2.0;
8228}

◆ shieldBoostFactor

- (float) shieldBoostFactor

Definition at line 2092 of file ShipEntity.m.

4058{
4059 float boostFactor = 1.0f;
4060 if ([self hasShieldBooster]) boostFactor += 1.0f;
4061 if ([self hasMilitaryShieldEnhancer]) boostFactor += 1.0f;
4062
4063 return boostFactor;
4064}
BOOL hasMilitaryShieldEnhancer()
BOOL hasShieldBooster()

◆ shieldRechargeRate

- (float) shieldRechargeRate

Definition at line 2092 of file ShipEntity.m.

4082{
4083 return [self hasMilitaryShieldEnhancer] ? 3.0f : 2.0f;
4084}

◆ shipAIScript

- (OOScript *) shipAIScript

Definition at line 14942 of file ShipEntity.m.

1403{
1404 return aiScript;
1405}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ shipAIScriptWakeTime

- (OOTimeAbsolute) shipAIScriptWakeTime

Definition at line 14942 of file ShipEntity.m.

1409{
1410 return aiScriptWakeTime;
1411}

◆ shipClassName

- (NSString *) shipClassName

◆ shipDataKey

- (NSString *) shipDataKey

Definition at line 14942 of file ShipEntity.m.

1974{
1975 return _shipKey;
1976}

Referenced by ShipGetProperty(), and ShipSetCargoType().

+ Here is the caller graph for this function:

◆ shipDataKeyAutoRole

- (NSString *) shipDataKeyAutoRole

Definition at line 14942 of file ShipEntity.m.

1980{
1981 return [[[NSString alloc] initWithFormat:@"[%@]",[self shipDataKey]] autorelease];
1982}

◆ shipHitByLaser

- (ShipEntity *) shipHitByLaser

Definition at line 9589 of file ShipEntity.m.

10171{
10172 return [_shipHitByLaser weakRefUnderlyingObject];
10173}

◆ shipInfoDictionary

- (NSDictionary *) shipInfoDictionary

Definition at line 14942 of file ShipEntity.m.

1993{
1994 return shipinfoDictionary;
1995}

Referenced by ShipSetMaterialsInternal().

+ Here is the caller graph for this function:

◆ shipRestoredFromDictionary:useFallback:context:

+ (id) shipRestoredFromDictionary: (NSDictionary *)  dictionary
useFallback: (BOOL)  fallback
context: (NSMutableDictionary *)  context 

Provided by category ShipEntity(LoadRestore).

Definition at line 362 of file ShipEntityLoadRestore.m.

173 :(NSDictionary *)dict
174 useFallback:(BOOL)fallback
175 context:(NSMutableDictionary *)context
176{
177 if (dict == nil) return nil;
178 if (context == nil) context = [NSMutableDictionary dictionary];
179
180 ShipEntity *ship = nil;
181
182 NSString *shipKey = [dict oo_stringForKey:KEY_SHIP_KEY];
183 NSDictionary *shipData = [[OOShipRegistry sharedRegistry] shipInfoForKey:shipKey];
184
185 if (shipData != nil)
186 {
187 NSMutableDictionary *mergedData = [NSMutableDictionary dictionaryWithDictionary:shipData];
188
189 StripIgnoredKeys(mergedData);
190 NSArray *deletes = [dict oo_arrayForKey:KEY_SHIPDATA_DELETES];
191 if (deletes != nil) [mergedData removeObjectsForKeys:deletes];
192 [mergedData addEntriesFromDictionary:[dict oo_dictionaryForKey:KEY_SHIPDATA_OVERRIDES]];
193 [mergedData oo_setBool:NO forKey:@"auto_ai"];
194 [mergedData oo_setUnsignedInteger:0 forKey:@"escorts"];
195
196 Class shipClass = [UNIVERSE shipClassForShipDictionary:mergedData];
197 ship = [[[shipClass alloc] initWithKey:shipKey definition:mergedData] autorelease];
198
199 // FIXME: restore AI.
200 [ship setAITo:[dict oo_stringForKey:KEY_AI defaultValue:@"nullAI.plist"]];
201
202 [ship setPrimaryRole:[dict oo_stringForKey:KEY_PRIMARY_ROLE]];
203
204 }
205 else
206 {
207 // Unknown ship; fall back on role if desired and possible.
208 NSString *shipPrimaryRole = [dict oo_stringForKey:KEY_PRIMARY_ROLE];
209 if (!fallback || shipPrimaryRole == nil) return nil;
210
211 ship = [[UNIVERSE newShipWithRole:shipPrimaryRole] autorelease];
212 if (ship == nil) return nil;
213 }
214
215 // The following stuff is deliberately set up the same way even if using role fallback.
216 [ship setPosition:[dict oo_hpvectorForKey:KEY_POSITION]];
217 [ship setNormalOrientation:[dict oo_quaternionForKey:KEY_ORIENTATION]];
218
219 float energyLevel = [dict oo_floatForKey:KEY_ENERGY_LEVEL defaultValue:1.0f];
220 [ship setEnergy:energyLevel * [ship maxEnergy]];
221
222 [ship removeAllEquipment];
223 NSString *eqKey = nil;
224 foreach (eqKey, [dict oo_arrayForKey:KEY_EQUIPMENT])
225 {
226 [ship addEquipmentItem:eqKey withValidation:NO inContext:@"loading"];
227 }
228
229 [ship removeMissiles];
230 foreach (eqKey, [dict oo_arrayForKey:KEY_MISSILES])
231 {
232 [ship addEquipmentItem:eqKey withValidation:NO inContext:@"loading"];
233 }
234
235 // Groups.
236 NSUInteger groupID = [dict oo_integerForKey:KEY_GROUP_ID defaultValue:NSNotFound];
237 if (groupID != NSNotFound)
238 {
239 OOShipGroup *group = GroupForGroupID(groupID, context);
240 [ship setGroup:group]; // Handles adding to group
241 if ([dict oo_boolForKey:KEY_IS_GROUP_LEADER]) [group setLeader:ship];
242 NSString *groupName = [dict oo_stringForKey:KEY_GROUP_NAME];
243 if (groupName != nil) [group setName:groupName];
244 if ([ship hasPrimaryRole:@"escort"] && ship != [group leader])
245 {
246 [ship setOwner:[group leader]];
247 }
248 }
249
250 groupID = [dict oo_integerForKey:KEY_ESCORT_GROUP_ID defaultValue:NSNotFound];
251 if (groupID != NSNotFound)
252 {
253 OOShipGroup *group = GroupForGroupID(groupID, context);
254 [group setLeader:ship];
255 [group setName:@"escort group"];
256 [ship setEscortGroup:group];
257 }
258
259 return ship;
260}
#define KEY_EQUIPMENT
#define KEY_MISSILES
static void StripIgnoredKeys(NSMutableDictionary *dict)
#define KEY_IS_GROUP_LEADER
static OOShipGroup * GroupForGroupID(NSUInteger groupID, NSMutableDictionary *context)
void setNormalOrientation:(Quaternion quat)
Definition Entity.m:745
void setName:(NSString *name)
NSDictionary * shipInfoForKey:(NSString *key)
BOOL addEquipmentItem:withValidation:inContext:(NSString *equipmentKey,[withValidation] BOOL validateAddition,[inContext] NSString *context)
OOCreditsQuantity removeMissiles()
void removeAllEquipment()
void setEscortGroup:(OOShipGroup *group)

◆ shipScript

- (OOScript *) shipScript

Definition at line 14942 of file ShipEntity.m.

1397{
1398 return script;
1399}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ shipSubEntityEnumerator

- (NSEnumerator *) shipSubEntityEnumerator

Definition at line 14942 of file ShipEntity.m.

1338{
1339 return [[self subEntities] objectEnumeratorFilteredWithSelector:@selector(isShip)];
1340}

◆ shipUniqueName

- (NSString *) shipUniqueName

◆ shortDescriptionComponents

- (NSString *) shortDescriptionComponents
implementation

Definition at line 14942 of file ShipEntity.m.

1200{
1201 return [NSString stringWithFormat:@"\"%@\"", [self name]];
1202}

◆ shotTime

- (OOTimeDelta) shotTime

Definition at line 9589 of file ShipEntity.m.

11626{
11627 return shot_time;
11628}

◆ showDamage

- (BOOL) showDamage

Definition at line 7616 of file ShipEntity.m.

9162{
9163 return _showDamage;
9164}

◆ showScoopMessage

- (BOOL) showScoopMessage

Definition at line 7616 of file ShipEntity.m.

8503{
8504 return hasScoopMessage;
8505}

◆ simplifyShipdata:andGetDeletes:

- (void) simplifyShipdata: (NSMutableDictionary *)  data
andGetDeletes: (NSArray **)  deletes 
implementation

Provided by category ShipEntity(LoadRestoreInternal).

Definition at line 362 of file ShipEntityLoadRestore.m.

263 :(NSMutableDictionary *)data andGetDeletes:(NSArray **)deletes
264{
265 NSParameterAssert(data != nil && deletes != NULL);
266 *deletes = nil;
267
268 // Get original ship data.
269 NSMutableDictionary *referenceData = [NSMutableDictionary dictionaryWithDictionary:[[OOShipRegistry sharedRegistry] shipInfoForKey:[self shipDataKey]]];
270
271 // Discard stuff that we handle separately.
272 StripIgnoredKeys(referenceData);
273 StripIgnoredKeys(data);
274
275 // Note items that are in referenceData, but not data.
276 NSMutableArray *foundDeletes = [NSMutableArray array];
277 NSString *key = nil;
278 foreachkey (key, referenceData)
279 {
280 if ([data objectForKey:key] == nil)
281 {
282 [foundDeletes addObject:key];
283 }
284 }
285 if ([foundDeletes count] != 0) *deletes = foundDeletes;
286
287 // after rev3010 this loop was using cycles without doing anything - commenting this whole loop out for now. -- kaks 20100207
288/*
289 // Discard anything that hasn't changed.
290 for (enumerator = [data keyEnumerator]; (key = [enumerator nextObject]); )
291 {
292 id referenceVal = [referenceData objectForKey:key];
293 id myVal = [data objectForKey:key];
294 if ([referenceVal isEqual:myVal])
295 {
296 // [data removeObjectForKey:key];
297 }
298 }
299*/
300}
#define foreachkey(VAR, DICT)
Definition OOCocoa.h:353

◆ spawn:

- (void) spawn: (NSString *)  roles_number

Definition at line 14062 of file ShipEntity.m.

14308 :(NSString *)roles_number
14309{
14310 NSArray *tokens = ScanTokensFromString(roles_number);
14311 NSString *roleString = nil;
14312 NSString *numberString = nil;
14313 NSUInteger number;
14314
14315 if ([tokens count] != 2)
14316 {
14317 OOLog(kOOLogSyntaxAddShips, @"***** Could not spawn: \"%@\" (must be two tokens, role and number)",roles_number);
14318 return;
14319 }
14320
14321 roleString = [tokens oo_stringAtIndex:0];
14322 numberString = [tokens oo_stringAtIndex:1];
14323
14324 number = [numberString intValue];
14325
14326 [self spawnShipsWithRole:roleString count:number];
14327}
static NSString *const kOOLogSyntaxAddShips

◆ spawnShipsWithRole:count:

- (NSArray *) spawnShipsWithRole: (NSString *)  role
count: (NSUInteger)  count 

Provided by category ShipEntity(ScriptMethods).

Definition at line 31 of file ShipEntityScriptMethods.m.

64 :(NSString *)role count:(NSUInteger)count
65{
66 ShipEntity *ship = [self rootShipEntity]; // FIXME: (EMMSTRAN) implement an -absolutePosition method, use that in spawnShipWithRole:near:, and use self instead of root.
67 ShipEntity *spawned = nil;
68 NSMutableArray *result = nil;
69
70 if (count == 0) return [NSArray array];
71
72 OOLog(kOOLogNoteAddShips, @"Spawning %llu x '%@' near %@ %d", count, role, [self shortDescription], [self universalID]);
73
74 result = [NSMutableArray arrayWithCapacity:count];
75
76 do
77 {
78 spawned = [UNIVERSE spawnShipWithRole:role near:ship];
79 if (spawned != nil)
80 {
81 [spawned setTemperature:[self randomEjectaTemperature]];
82 if ([self isMissileFlagSet] && [[spawned shipInfoDictionary] oo_boolForKey:@"is_submunition"])
83 {
84 [spawned setOwner:[self owner]];
85 [spawned addTarget:[self primaryTarget]];
86 [spawned setIsMissileFlag:YES];
87 }
88 if ([spawned isMine])
89 {
90 [spawned setOwner:self];
91 }
92 [result addObject:spawned];
93 }
94 }
95 while (--count);
96
97 return result;
98}
static NSString *const kOOLogNoteAddShips

Referenced by ShipSpawn().

+ Here is the caller graph for this function:

◆ speedFactor

- (GLfloat) speedFactor

Definition at line 7616 of file ShipEntity.m.

8775{
8776 if (maxFlightSpeed <= 0.0) return 0.0;
8777 return flightSpeed / maxFlightSpeed;
8778}

◆ starboardWeaponOffset

- (NSArray *) starboardWeaponOffset

◆ startTrackingCurve

- (void) startTrackingCurve

Definition at line 2092 of file ShipEntity.m.

6313{
6314 Entity *target = [self primaryTarget];
6315 if (target == nil)
6316 {
6317 return;
6318 }
6319 OOTimeAbsolute now = [UNIVERSE getTime];
6320 trackingCurvePositions[0] = [target position];
6321 trackingCurvePositions[1] = [target position];
6322 trackingCurvePositions[2] = [target position];
6323 trackingCurvePositions[3] = [target position];
6324 trackingCurveTimes[0] = now;
6325 trackingCurveTimes[1] = now - reactionTime/3.0;
6326 trackingCurveTimes[2] = now - reactionTime*2.0/3.0;
6328 [self calculateTrackingCurve];
6329 return;
6330}

◆ stationGroup

- (OOShipGroup *) stationGroup

Definition at line 6493 of file ShipEntity.m.

6962{
6963 if (_group == nil)
6964 {
6965 _group = [[OOShipGroup alloc] initWithName:@"station group"];
6966 [_group setLeader:self];
6967 }
6968
6969 return _group;
6970}

◆ storeTarget

- (void) storeTarget
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2119{
2120 Entity *target = [self primaryTarget];
2121
2122 if (target)
2123 {
2124 [self setRememberedShip:target];
2125 }
2126 else
2127 {
2128 DESTROY(_rememberedShip);
2129 }
2130
2131}

◆ subEntities

- (NSArray *) subEntities

◆ subEntitiesForScript

- (NSArray *) subEntitiesForScript

Provided by category ShipEntity(OOJavaScriptExtensions).

Definition at line 1 of file EntityOOJavaScriptExtensions.m.

135{
136 return [[self shipSubEntityEnumerator] allObjects];
137}

Referenced by ShipGetProperty(), and ShipRestoreSubEntities().

+ Here is the caller graph for this function:

◆ subEntityCount

- (NSUInteger) subEntityCount

Definition at line 14942 of file ShipEntity.m.

1320{
1321 return [subEntities count];
1322}

◆ subEntityDied:

- (void) subEntityDied: (ShipEntity *)  sub
implementation

Provided by category ShipEntity(Private).

Definition at line 7616 of file ShipEntity.m.

9516 :(ShipEntity *)sub
9517{
9518 if ([self subEntityTakingDamage] == sub) [self setSubEntityTakingDamage:nil];
9519
9520 [sub setOwner:nil];
9521 // TODO? Recalculating collision radius should increase collision testing efficiency,
9522 // but for most ship models the difference would be marginal. -- Kaks 20110429
9523 mass -= [sub mass]; // missing subents affect fuel charge rate, etc..
9524 [subEntities removeObject:sub];
9525}

◆ subEntityEnumerator

- (NSEnumerator *) subEntityEnumerator

Definition at line 14942 of file ShipEntity.m.

1332{
1333 return [[self subEntities] objectEnumerator];
1334}

◆ subEntityReallyDied:

- (void) subEntityReallyDied: (ShipEntity *)  sub
implementation

Reimplemented from Entity.

Provided by category ShipEntity(Private).

Definition at line 7616 of file ShipEntity.m.

9528 :(ShipEntity *)sub
9529{
9530 if ([self subEntityTakingDamage] == sub) [self setSubEntityTakingDamage:nil];
9531
9532 if ([self hasSubEntity:sub])
9533 {
9534 OOLogERR(@"shipEntity.bug.subEntityRetainUnderflow", @"Subentity of %@ died while still in subentity list! This is bad. Leaking subentity list to avoid crash. %@", self, @"This is an internal error, please report it.");
9535
9536 // Leak subentity list.
9537 subEntities = nil;
9538 }
9539}

◆ subEntityRotationalVelocity

- (Quaternion) subEntityRotationalVelocity

Definition at line 14942 of file ShipEntity.m.

1170{
1172}

◆ subEntityTakingDamage

- (ShipEntity *) subEntityTakingDamage

Definition at line 14942 of file ShipEntity.m.

1356{
1357 ShipEntity *result = [_subEntityTakingDamage weakRefUnderlyingObject];
1358
1359#ifndef NDEBUG
1360 // Sanity check - there have been problems here, see fireLaserShotInDirection:
1361 // -parentEntity will take care of reporting insanity.
1362 if ([result parentEntity] != self) result = nil;
1363#endif
1364
1365 // Clear the weakref if the subentity is dead.
1366 if (result == nil) [self setSubEntityTakingDamage:nil];
1367
1368 return result;
1369}

◆ subIdx

- (NSUInteger) subIdx

Definition at line 14942 of file ShipEntity.m.

787{
788 return _subIdx;
789}

◆ suggestEscort

- (void) suggestEscort
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1826{
1827 ShipEntity *mother = [self primaryTarget];
1828 [self suggestEscortTo:mother];
1829}

◆ suggestEscortTo:

- (BOOL) suggestEscortTo: (ShipEntity *)  mother

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

717 :(ShipEntity *)mother
718{
719 if (mother)
720 {
721#ifndef NDEBUG
722 if (reportAIMessages)
723 {
724 OOLog(@"ai.suggestEscort", @"DEBUG: %@ suggests escorting %@", self, mother);
725 }
726#endif
727
728 if ([mother acceptAsEscort:self])
729 {
730 // copy legal status across
731 if (([mother legalStatus] > 0)&&(bounty <= 0))
732 {
733 int extra = 1 | (ranrot_rand() & 15);
734// [mother setBounty: [mother legalStatus] + extra withReason:kOOLegalStatusReasonAssistingOffender];
735 [self markAsOffender:extra withReason:kOOLegalStatusReasonAssistingOffender];
736 // bounty += extra; // obviously we're dodgier than we thought!
737 }
738
739 [self setOwner:mother];
740 [self setGroup:[mother escortGroup]];
741 [shipAI message:@"ESCORTING"];
742 return YES;
743 }
744
745#ifndef NDEBUG
746 if (reportAIMessages)
747 {
748 OOLog(@"ai.suggestEscort.refused", @"DEBUG: %@ refused by %@", self, mother);
749 }
750#endif
751
752 }
753 [self setOwner:self];
754 [shipAI message:@"NOT_ESCORTING"];
755 [self doScriptEvent:OOJSID("escortRejected") withArgument:mother];
756 return NO;
757}

◆ sunGlareFilter

- (GLfloat) sunGlareFilter

◆ suppressFlightNotifications

- (BOOL) suppressFlightNotifications

Definition at line 14942 of file ShipEntity.m.

2057{
2058 return suppressAegisMessages;
2059}

◆ suppressTargetLost

- (void) suppressTargetLost
implementation

Reimplemented in PlayerEntity.

Definition at line 9589 of file ShipEntity.m.

12907{
12908
12909}

◆ SurfaceDistanceSqared

+ (static float) SurfaceDistanceSqared (Entity *)  reference
(Entity< OOStellarBody > *)  stellar 
implementation

Definition at line 7610 of file ShipEntity.m.

7611{
7612 return SurfaceDistanceSqaredV([reference position], stellar);
7613}

◆ SurfaceDistanceSqaredV

+ (static float) SurfaceDistanceSqaredV (HPVector)  reference
(Entity< OOStellarBody > *)  stellar 
implementation

Definition at line 7599 of file ShipEntity.m.

7600{
7601 float centerDistance = HPmagnitude2(HPvector_subtract([stellar position], reference));
7602 float r = [stellar radius];
7603 /* 1.35: empirical value used to help determine proximity when non-nested
7604 planets are close to each other
7605 */
7606 return centerDistance - 1.35 * r * r;
7607}

◆ switchAITo:

- (void) switchAITo: (NSString *)  aiString

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

307 :(NSString *)aiString
308{
309 [self setAITo:aiString];
310 [[self getAI] clearStack];
311}

Referenced by ShipSwitchAI().

+ Here is the caller graph for this function:

◆ switchLightsOff

- (void) switchLightsOff

Definition at line 9589 of file ShipEntity.m.

13643{
13644 OOFlasherEntity *se = nil;
13645 ShipEntity *sub = nil;
13646
13647 _lightsActive = NO;
13648
13649 foreach (se, [self flasherEnumerator])
13650 {
13651 [se setActive:NO];
13652 }
13653 foreach (sub, [self shipSubEntityEnumerator])
13654 {
13655 [sub switchLightsOff];
13656 }
13657}
void setActive:(BOOL active)
NSEnumerator * flasherEnumerator()
void switchLightsOff()

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ switchLightsOn

- (void) switchLightsOn

Definition at line 9589 of file ShipEntity.m.

13625{
13626 OOFlasherEntity *se = nil;
13627 ShipEntity *sub = nil;
13628
13629 _lightsActive = YES;
13630
13631 foreach (se, [self flasherEnumerator])
13632 {
13633 [se setActive:YES];
13634 }
13635 foreach (sub, [self shipSubEntityEnumerator])
13636 {
13637 [sub switchLightsOn];
13638 }
13639}
void switchLightsOn()

Referenced by ShipSetProperty().

+ Here is the caller graph for this function:

◆ takeEnergyDamage:from:becauseOf:weaponIdentifier:

- (void) takeEnergyDamage: (double)  amount
from: (Entity *)  ent
becauseOf: (Entity *)  other
weaponIdentifier: (NSString *)  weaponIdentifier 
implementation

Reimplemented from Entity.

Reimplemented in DockEntity, PlayerEntity, and StationEntity.

Definition at line 9589 of file ShipEntity.m.

13119 :(double)amount from:(Entity *)ent becauseOf:(Entity *)other weaponIdentifier:(NSString *)weaponIdentifier
13120{
13121 if ([self status] == STATUS_DEAD) return;
13122 if (amount <= 0.0) return;
13123
13124 BOOL energyMine = [ent isCascadeWeapon];
13125 BOOL cascade = NO;
13126 if (energyMine)
13127 {
13128 cascade = [self cascadeIfAppropriateWithDamageAmount:amount cascadeOwner:[ent owner]];
13129 }
13130
13131 energy -= amount;
13132 /* Heat increase from energy impacts will never directly cause
13133 * overheating - too easy for missile hits to cause an uncredited
13134 * death by overheating - CIM */
13136 {
13139 {
13141 }
13142 }
13143
13144
13145 being_mined = NO;
13146 ShipEntity *hunter = nil;
13147
13148 hunter = [other rootShipEntity];
13149 if (hunter == nil && [other isShip]) hunter = (ShipEntity *)other;
13150
13151 // must check for this before potentially deleting 'other' for cloaking
13152 if ((other)&&([other isShip]))
13153 {
13154 being_mined = [(ShipEntity *)other isMining];
13155 }
13156
13157 if (hunter !=nil && [self owner] != hunter) // our owner could be the same entity as the one responsible for our taking damage in the case of submunitions
13158 {
13159 if ([hunter isCloaked])
13160 {
13161 [self doScriptEvent:OOJSID("shipBeingAttackedByCloaked") andReactToAIMessage:@"ATTACKED_BY_CLOAKED"];
13162
13163 // lose it!
13164 other = nil;
13165 hunter = nil;
13166 }
13167 }
13168 else
13169 {
13170 hunter = nil;
13171 }
13172
13173 // if the other entity is a ship note it as an aggressor
13174 if (hunter != nil)
13175 {
13176 BOOL iAmTheLaw = [self isPolice];
13177 BOOL uAreTheLaw = [hunter isPolice];
13178
13179 DESTROY(_lastEscortTarget); // we're being attacked, escorts can scramble!
13180
13181 [self setPrimaryAggressor:hunter];
13182 [self setFoundTarget:hunter];
13183
13184 // firing on an innocent ship is an offence
13185 [self broadcastHitByLaserFrom: hunter];
13186
13187 // tell ourselves we've been attacked
13188 if (energy > 0)
13189 {
13190 [self respondToAttackFrom:ent becauseOf:hunter];
13191 }
13192
13193 OOShipGroup *group = [self group];
13194 // JSAIs manage group notifications themselves
13195 if (![self hasNewAI])
13196 {
13197 // additionally, tell our group we've been attacked
13198 if (group != nil && group != [hunter group] && !(iAmTheLaw || uAreTheLaw))
13199 {
13200 if ([self isTrader] || [self isEscort])
13201 {
13202 ShipEntity *groupLeader = [group leader];
13203 if (groupLeader != self)
13204 {
13205 [groupLeader setFoundTarget:hunter];
13206 [groupLeader setPrimaryAggressor:hunter];
13207 [groupLeader respondToAttackFrom:ent becauseOf:hunter];
13208 //unsetting group leader for carriers can break stuff
13209 }
13210 }
13211 if ([self isPirate])
13212 {
13213 NSEnumerator *groupEnum = nil;
13214 ShipEntity *otherPirate = nil;
13215
13216 for (groupEnum = [group mutationSafeEnumerator]; (otherPirate = [groupEnum nextObject]); )
13217 {
13218 if (otherPirate != self && randf() < 0.5) // 50% chance they'll help
13219 {
13220 [otherPirate setFoundTarget:hunter];
13221 [otherPirate setPrimaryAggressor:hunter];
13222 [otherPirate respondToAttackFrom:ent becauseOf:hunter];
13223 }
13224 }
13225 }
13226 else if (iAmTheLaw)
13227 {
13228 NSEnumerator *groupEnum = nil;
13229 ShipEntity *otherPolice = nil;
13230
13231 for (groupEnum = [group mutationSafeEnumerator]; (otherPolice = [groupEnum nextObject]); )
13232 {
13233 if (otherPolice != self)
13234 {
13235 [otherPolice setFoundTarget:hunter];
13236 [otherPolice setPrimaryAggressor:hunter];
13237 [otherPolice respondToAttackFrom:ent becauseOf:hunter];
13238 }
13239 }
13240 }
13241 }
13242 }
13243
13244 // if I'm a copper and you're not, then mark the other as an offender!
13245 if (iAmTheLaw && !uAreTheLaw)
13246 {
13247 // JSAI's can choose not to do this for friendly fire purposes
13248 if (![self hasNewAI])
13249 {
13250 [hunter markAsOffender:64 withReason:kOOLegalStatusReasonAttackedPolice];
13251 }
13252 }
13253
13254 if ((group != nil && [hunter group] == group) || (iAmTheLaw && uAreTheLaw))
13255 {
13256 // avoid shooting each other
13257 if ([hunter behaviour] == BEHAVIOUR_ATTACK_FLY_TO_TARGET) // avoid me please!
13258 {
13259 [hunter setBehaviour:BEHAVIOUR_ATTACK_FLY_FROM_TARGET];
13260 [hunter setDesiredSpeed:[hunter maxFlightSpeed]];
13261 }
13262 }
13263
13264 }
13265
13266 OOShipDamageType damageType = kOODamageTypeEnergy;
13267 if (suppressExplosion) damageType = kOODamageTypeRemoved;
13268 else if (energyMine) damageType = kOODamageTypeCascadeWeapon;
13269
13270 if (!suppressExplosion)
13271 {
13272 [self noteTakingDamage:amount from:other type:damageType];
13273 if (cascade) energy = 0.0; // explicit set energy to zero in case an oxp raised the energy in previous line.
13274 }
13275
13276 // die if I'm out of energy
13277 if (energy <= 0.0)
13278 {
13279 // backup check just in case scripts have reduced energy
13280 if (self != [UNIVERSE station])
13281 {
13282 if (hunter != nil) [hunter noteTargetDestroyed:self];
13283 [self getDestroyedBy:other damageType:damageType];
13284 }
13285 }
13286 else
13287 {
13288 // warn if I'm low on energy
13289 if (energy < maxEnergy * 0.25)
13290 {
13291 [self doScriptEvent:OOJSID("shipEnergyIsLow") andReactToAIMessage:@"ENERGY_LOW"];
13292 }
13293 if ((energy < maxEnergy *0.125 || (energy < 64 && energy < amount*2)) && [self hasEscapePod] && (ranrot_rand() & 3) == 0) // 25% chance he gets to an escape pod
13294 {
13295 [self abandonShip];
13296 }
13297 }
13298}
#define SHIP_ENERGY_DAMAGE_TO_HEAT_FACTOR
Definition ShipEntity.h:65
ShipEntity * rootShipEntity()
Definition Entity.m:604
BOOL isPirate()
void setDesiredSpeed:(double amount)
BOOL isTrader()
void noteTargetDestroyed:(ShipEntity *target)

◆ takeHeatDamage:

- (void) takeHeatDamage: (double)  amount

Reimplemented in PlayerEntity, and StationEntity.

Definition at line 9589 of file ShipEntity.m.

13417 :(double)amount
13418{
13419 if ([self status] == STATUS_DEAD) return;
13420
13421 if ([self isSubEntity])
13422 {
13423 ShipEntity* owner = [self owner];
13424 if (![owner isFrangible])
13425 {
13426 return;
13427 }
13428 }
13429
13430 energy -= amount;
13431 throw_sparks = YES;
13432
13433 [self noteTakingDamage:amount from:nil type:kOODamageTypeHeat];
13434
13435 // oops we're burning up!
13436 if (energy <= 0.0)
13437 {
13438 [self getDestroyedBy:nil damageType:kOODamageTypeHeat];
13439 }
13440 else
13441 {
13442 // warn if I'm low on energy
13443 if (energy < maxEnergy * 0.25)
13444 {
13445 [self doScriptEvent:OOJSID("shipEnergyIsLow") andReactToAIMessage:@"ENERGY_LOW"];
13446 }
13447 }
13448}
unsigned throw_sparks
Definition Entity.h:101

◆ takeScrapeDamage:from:

- (void) takeScrapeDamage: (double)  amount
from: (Entity *)  ent 

Reimplemented in PlayerEntity, and StationEntity.

Definition at line 9589 of file ShipEntity.m.

13373 :(double) amount from:(Entity *)ent
13374{
13375 if ([self status] == STATUS_DEAD) return;
13376
13377 if ([self status] == STATUS_LAUNCHING|| [ent status] == STATUS_LAUNCHING)
13378 {
13379 // no collisions during launches please
13380 return;
13381 }
13382
13383 energy -= amount;
13384 [self noteTakingDamage:amount from:ent type:kOODamageTypeScrape];
13385
13386 // oops we hit too hard!!!
13387 if (energy <= 0.0)
13388 {
13389 float frag_chance = [ent mass]*10/[self mass];
13390 /* impacts from heavier entities produce fragments
13391 * impacts from lighter entities might do but not always
13392 * asteroid-asteroid impacts likely to fragment
13393 * ship-asteroid impacts might, or might just vaporise it
13394 * projectile weapons just get the default chance
13395 */
13396 if (randf() < frag_chance)
13397 {
13398 being_mined = YES; // same as using a mining laser
13399 }
13400 if ([ent isShip])
13401 {
13402 [(ShipEntity *)ent noteTargetDestroyed:self];
13403 }
13404 [self getDestroyedBy:ent damageType:kOODamageTypeScrape];
13405 }
13406 else
13407 {
13408 // warn if I'm low on energy
13409 if (energy < maxEnergy * 0.25)
13410 {
13411 [self doScriptEvent:OOJSID("shipEnergyIsLow") andReactToAIMessage:@"ENERGY_LOW"];
13412 }
13413 }
13414}

◆ targetFirstBeaconWithCode:

- (void) targetFirstBeaconWithCode: (NSString *)  code
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2653 :(NSString*) code
2654{
2655 NSArray *all_beacons = [UNIVERSE listBeaconsWithCode: code];
2656 if ([all_beacons count])
2657 {
2658 [self addTarget:(ShipEntity*)[all_beacons objectAtIndex:0]];
2659 [shipAI message:@"TARGET_FOUND"];
2660 }
2661 else
2662 [shipAI message:@"NOTHING_FOUND"];
2663}

◆ targetNextBeaconWithCode:

- (void) targetNextBeaconWithCode: (NSString *)  code
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

2666 :(NSString*) code
2667{
2668 NSArray *all_beacons = [UNIVERSE listBeaconsWithCode: code];
2669 ShipEntity *current_beacon = [self primaryTarget];
2670
2671 if ((!current_beacon)||(![current_beacon isBeacon]))
2672 {
2673 [shipAI message:@"NO_CURRENT_BEACON"];
2674 [shipAI message:@"NOTHING_FOUND"];
2675 return;
2676 }
2677
2678 // find the current beacon in the list..
2679 NSUInteger i = [all_beacons indexOfObject:current_beacon];
2680
2681 if (i == NSNotFound)
2682 {
2683 [shipAI message:@"NOTHING_FOUND"];
2684 return;
2685 }
2686
2687 i++; // next index
2688
2689 if (i < [all_beacons count])
2690 {
2691 // locate current target in list
2692 [self addTarget:(ShipEntity*)[all_beacons objectAtIndex:i]];
2693 [shipAI message:@"TARGET_FOUND"];
2694 }
2695 else
2696 {
2697 [shipAI message:@"LAST_BEACON"];
2698 [shipAI message:@"NOTHING_FOUND"];
2699 }
2700}

◆ targetStation

- (StationEntity *) targetStation

Definition at line 9589 of file ShipEntity.m.

10008{
10009 StationEntity *result = [_targetStation weakRefUnderlyingObject];
10010 if (result == nil || ![self isValidTarget:result])
10011 {
10013 return nil;
10014 }
10015 return result;
10016}

◆ temperature

- (GLfloat) temperature

Definition at line 7616 of file ShipEntity.m.

8782{
8783 return ship_temperature;
8784}

◆ thankedShip

- (Entity *) thankedShip

Definition at line 9589 of file ShipEntity.m.

9970{
9971 Entity *result = [_thankedShip weakRefUnderlyingObject];
9972 if (result == nil || ![self isValidTarget:result])
9973 {
9975 return nil;
9976 }
9977 return result;
9978}

◆ thargonCheckMother

- (void) thargonCheckMother
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1716{
1717 ShipEntity *mother = [self owner];
1718 if (mother == nil && [self group]) mother = [[self group] leader];
1719
1720 double maxRange2 = scannerRange * scannerRange;
1721
1722 if (mother && mother != self && HPdistance2(mother->position, position) < maxRange2)
1723 {
1724 [shipAI message:@"TARGET_FOUND"]; // no need for scanning, we still have our mother.
1725 }
1726 else
1727 {
1728 // we lost the old mother, search for a new one
1729 [self scanForNearestShipHavingRole:@"thargoid-mothership"]; // the scan will send further AI messages.
1730 if ([self foundTarget] != nil)
1731 {
1732 mother = (ShipEntity*)[self foundTarget];
1733 [self setOwner:mother];
1734 if ([mother group] != [mother escortGroup]) // avoid adding thargon to an escort group.
1735 {
1736 [self setGroup:[mother group]];
1737 }
1738 };
1739 }
1740}

◆ throwSparks

- (void) throwSparks
implementation

Reimplemented from Entity.

Definition at line 9589 of file ShipEntity.m.

12092{
12093 Vector offset =
12094 {
12095 randf() * (boundingBox.max.x - boundingBox.min.x) + boundingBox.min.x,
12096 randf() * (boundingBox.max.y - boundingBox.min.y) + boundingBox.min.y,
12097 randf() * boundingBox.max.z + boundingBox.min.z // rear section only
12098 };
12099 HPVector origin = HPvector_add(position, vectorToHPVector(quaternion_rotate_vector([self normalOrientation], offset)));
12100
12101 float w = boundingBox.max.x - boundingBox.min.x;
12102 float h = boundingBox.max.y - boundingBox.min.y;
12103 float m = (w < h) ? 0.25 * w: 0.25 * h;
12104
12105 float sz = m * (1 + randf() + randf()); // half minimum dimension on average
12106
12107 Vector vel = vector_multiply_scalar(HPVectorToVector(HPvector_subtract(origin, position)), 2.0);
12108
12109 OOColor *color = [OOColor colorWithHue:0.08 + 0.17 * randf() saturation:1.0 brightness:1.0 alpha:1.0];
12110
12111 OOSparkEntity *spark = [[OOSparkEntity alloc] initWithPosition:origin
12112 velocity:vel
12113 duration:2.0 + 3.0 * randf()
12114 size:sz
12115 color:color];
12116
12117 [spark setOwner:self];
12118 [UNIVERSE addEntity:spark];
12119 [spark release];
12120
12122}
double next_spark_time
Definition ShipEntity.h:384

◆ thrust

- (float) thrust

◆ thrustVector

- (Vector) thrustVector

Definition at line 9589 of file ShipEntity.m.

12825{
12826 return vector_multiply_scalar(v_forward, flightSpeed);
12827}

◆ totalBoundingBox

- (BoundingBox) totalBoundingBox

◆ trackCloseContacts

- (BOOL) trackCloseContacts

◆ trackDestination:delta_t:

- (double) trackDestination: (double) 
delta_t: (BOOL)  retreat 

Definition at line 9589 of file ShipEntity.m.

10924 :(double) delta_t :(BOOL) retreat
10925{
10926 Vector relPos;
10927 GLfloat d_forward, d_up, d_right;
10928
10929 BOOL we_are_docking = (nil != dockingInstructions);
10930
10931 stick_roll = 0.0; //desired roll and pitch
10932 stick_pitch = 0.0;
10933 stick_yaw = 0.0;
10934
10935 double reverse = 1.0;
10936 double reversePlayer = 1.0;
10937
10938 double min_d = 0.004;
10939 double max_cos = MAX_COS; // should match default value of max_cos in behaviour_fly_to_destination!
10940 double precision = we_are_docking ? 0.25 : 0.9025; // lower values force a direction closer to the target. (resp. 50% and 95% within range)
10941
10942 if (retreat)
10943 reverse = -reverse;
10944
10945 if (isPlayer)
10946 {
10947 reverse = -reverse;
10948 reversePlayer = -1;
10949 }
10950
10951 relPos = HPVectorToVector(HPvector_subtract(_destination, position));
10952 double range2 = magnitude2(relPos);
10953 double desired_range2 = desired_range*desired_range;
10954
10955 /* 2009-7-18 Eric: We need to aim well inide the desired_range sphere round the target and not at the surface of the sphere.
10956 Because of the framerate most ships normally overshoot the target and they end up flying clearly on a path
10957 through the sphere. Those ships give no problems, but ships with a very low turnrate will aim close to the surface and will than
10958 have large trouble with reaching their destination. When those ships enter the slowdown range, they have almost no speed vector
10959 in the direction of the target. I now used 95% of desired_range to aim at, but a smaller value might even be better.
10960 */
10961 if (range2 > desired_range2)
10962 {
10963 max_cos = sqrt(1 - precision * desired_range2/range2); // Head for a point within 95% of desired_range.
10964 if (max_cos >= 0.99999)
10965 {
10966 max_cos = 0.99999;
10967 }
10968 }
10969
10970 if (!vector_equal(relPos, kZeroVector)) relPos = vector_normal(relPos);
10971 else relPos.z = 1.0;
10972
10973 d_right = dot_product(relPos, v_right);
10974 d_up = dot_product(relPos, v_up);
10975 d_forward = dot_product(relPos, v_forward); // == cos of angle between v_forward and vector to target
10976
10977 // begin rule-of-thumb manoeuvres
10978 stick_pitch = 0.0;
10979 stick_roll = 0.0;
10980
10981 // pitching_over is currently only set in behaviour_formation_form_up, for escorts and in avoidCollision.
10982 // This allows for immediate pitch corrections instead of first waiting untill roll has completed.
10983 if (pitching_over)
10984 {
10985 if (reverse * d_up > 0) // pitch up
10987 else
10989 pitching_over = (reverse * d_forward < 0.707);
10990 }
10991
10992 // check if we are flying toward (or away from) the destination..
10993 if ((d_forward < max_cos)||(retreat)) // not on course so we must adjust controls..
10994 {
10995
10996 if (d_forward <= -max_cos || (retreat && d_forward >= max_cos)) // hack to avoid just flying away from the destination
10997 {
10998 d_up = min_d * 2.0;
10999 }
11000
11001 if (d_up > min_d)
11002 {
11003 int factor = sqrt(fabs(d_right) / fabs(min_d));
11004 if (factor > 8)
11005 factor = 8;
11006 if (d_right > min_d)
11007 stick_roll = - max_flight_roll * reversePlayer * 0.125 * factor; // only reverse sign for the player;
11008 if (d_right < -min_d)
11009 stick_roll = + max_flight_roll * reversePlayer * 0.125 * factor;
11010 if (fabs(d_right) < fabs(stick_roll) * delta_t)
11011 stick_roll = fabs(d_right) / delta_t * (stick_roll<0 ? -1 : 1); // don't overshoot heading
11012 }
11013
11014 if (d_up < -min_d)
11015 {
11016 int factor = sqrt(fabs(d_right) / fabs(min_d));
11017 if (factor > 8)
11018 factor = 8;
11019 if (d_right > min_d)
11020 stick_roll = + max_flight_roll * reversePlayer * 0.125 * factor; // only reverse sign for the player;
11021 if (d_right < -min_d)
11022 stick_roll = - max_flight_roll * reversePlayer * 0.125 * factor;
11023 if (fabs(d_right) < fabs(stick_roll) * delta_t)
11024 stick_roll = fabs(d_right) / delta_t * (stick_roll<0 ? -1 : 1); // don't overshoot heading
11025 }
11026
11027 if (stick_roll == 0.0)
11028 {
11029 int factor = sqrt(fabs(d_up) / fabs(min_d));
11030 if (factor > 8)
11031 factor = 8;
11032 if (d_up > min_d)
11033 stick_pitch = - max_flight_pitch * reverse * 0.125 * factor; //pitch_pitch * reverse;
11034 if (d_up < -min_d)
11035 stick_pitch = + max_flight_pitch * reverse * 0.125 * factor;
11036 if (fabs(d_up) < fabs(stick_pitch) * delta_t)
11037 stick_pitch = fabs(d_up) / delta_t * (stick_pitch<0 ? -1 : 1); // don't overshoot heading
11038 }
11039
11040 if (stick_pitch == 0.0)
11041 {
11042 // not sufficiently on course yet, but min_d is too high
11043 // turn anyway slightly to adjust
11044 stick_pitch = 0.01;
11045 }
11046 }
11047
11048 if (we_are_docking && docking_match_rotation && (d_forward > max_cos))
11049 {
11050 /* we are docking and need to consider the rotation/orientation of the docking port */
11051 StationEntity* station_for_docking = (StationEntity*)[self targetStation];
11052
11053 if ((station_for_docking)&&(station_for_docking->isStation))
11054 {
11055 stick_roll = [self rollToMatchUp:[station_for_docking portUpVectorForShip:self] rotating:[station_for_docking flightRoll]];
11056 }
11057 }
11058
11059 // end rule-of-thumb manoeuvres
11060
11061 [self applySticks:delta_t];
11062
11063 if (retreat)
11064 d_forward *= d_forward; // make positive AND decrease granularity
11065
11066 if (d_forward < 0.0)
11067 return 0.0;
11068
11069 if ((!flightRoll)&&(!flightPitch)) // no correction
11070 return 1.0;
11071
11072 return d_forward;
11073}
Vector portUpVectorForShip:(ShipEntity *ship)

◆ trackOntoTarget:withDForward:

- (void) trackOntoTarget: (double)  delta_t
withDForward: (GLfloat)  dp 

Definition at line 9589 of file ShipEntity.m.

10286 :(double) delta_t withDForward: (GLfloat) dp
10287{
10288 Vector vector_to_target;
10289 Quaternion q_minarc;
10290 //
10291 Entity* target = [self primaryTarget];
10292 //
10293 if (!target)
10294 return;
10295
10296 vector_to_target = [self vectorTo:target];
10297 //
10298 GLfloat range2 = magnitude2(vector_to_target);
10299 GLfloat targetRadius = 0.75 * target->collision_radius;
10300 GLfloat max_cos = sqrt(1 - targetRadius*targetRadius/range2);
10301
10302 if (dp > max_cos)
10303 return; // ON TARGET!
10304
10305 if (vector_to_target.x||vector_to_target.y||vector_to_target.z)
10306 vector_to_target = vector_normal(vector_to_target);
10307 else
10308 vector_to_target.z = 1.0;
10309
10310 q_minarc = quaternion_rotation_between(v_forward, vector_to_target);
10311
10313 [self orientationChanged];
10314
10315 flightRoll = 0.0;
10316 flightPitch = 0.0;
10317 flightYaw = 0.0;
10318 stick_roll = 0.0;
10319 stick_pitch = 0.0;
10320 stick_yaw = 0.0;
10321}

◆ trackPrimaryTarget:delta_t:

- (double) trackPrimaryTarget: (double) 
delta_t: (BOOL)  retreat 

Definition at line 9589 of file ShipEntity.m.

10471 :(double) delta_t :(BOOL) retreat
10472{
10473 Entity* target = [self primaryTarget];
10474
10475 if (!target) // leave now!
10476 {
10477 [self noteLostTargetAndGoIdle]; // NOTE: was AI message: rather than reactToMessage:
10478 return 0.0;
10479 }
10480
10481 if (![self canStillTrackPrimaryTarget])
10482 {
10483 [self noteLostTargetAndGoIdle]; // NOTE: was AI message: rather than reactToMessage:
10484 return 0.0;
10485 }
10486
10487 /* 1.81 change: do the above check first: if a missile can't be
10488 * fired outside scanner range it should self-destruct if the
10489 * target gets far enough away (it's going to miss anyway) -
10490 * CIM */
10491 if (scanClass == CLASS_MISSILE)
10492 return [self missileTrackPrimaryTarget: delta_t];
10493
10494 GLfloat d_forward, d_up, d_right;
10495
10496 Vector relPos = HPVectorToVector(HPvector_subtract([self calculateTargetPosition], position));
10497
10498 double range2 = HPmagnitude2(HPvector_subtract([target position], position));
10499
10500 //jink if retreating
10501 if (retreat) // calculate jink position when flying away from target.
10502 {
10503 Vector vx, vy, vz;
10504 if (target->isShip)
10505 {
10506 ShipEntity* targetShip = (ShipEntity*)target;
10507 vx = targetShip->v_right;
10508 vy = targetShip->v_up;
10509 vz = targetShip->v_forward;
10510 }
10511 else
10512 {
10513 Quaternion q = target->orientation;
10517 }
10518
10519 BOOL avoidCollision = NO;
10520 if (range2 < collision_radius * target->collision_radius * 100.0) // Check direction within 10 * collision radius.
10521 {
10522 Vector targetDirection = kBasisZVector;
10523 if (!vector_equal(relPos, kZeroVector)) targetDirection = vector_normal(relPos);
10524 avoidCollision = (dot_product(targetDirection, v_forward) > -0.1); // is flying toward target or only slightly outward.
10525 }
10526
10527 GLfloat dist_adjust_factor = 1.0;
10529 {
10530 double range = magnitude(relPos);
10531 if (range > 2000.0)
10532 {
10533 dist_adjust_factor = range / 2000.0;
10535 {
10536 dist_adjust_factor *= 3;
10537 }
10538 }
10539 if (jink.x == 0.0 && behaviour != BEHAVIOUR_RUNNING_DEFENSE)
10540 { // test for zero jink and correct
10541 [self setEvasiveJink:400.0];
10542 }
10543 }
10544
10545 if (!avoidCollision) // it is safe to jink
10546 {
10547 relPos.x += (jink.x * vx.x + jink.y * vy.x + jink.z * vz.x) * dist_adjust_factor;
10548 relPos.y += (jink.x * vx.y + jink.y * vy.y + jink.z * vz.y) * dist_adjust_factor;
10549 relPos.z += (jink.x * vx.z + jink.y * vy.z + jink.z * vz.z);
10550 }
10551
10552 }
10553
10554 if (!vector_equal(relPos, kZeroVector)) relPos = vector_normal(relPos);
10555 else relPos.z = 1.0;
10556
10557 double max_cos = [self currentAimTolerance];
10558
10559 stick_roll = 0.0; //desired roll and pitch
10560 stick_pitch = 0.0;
10561
10562 double reverse = (retreat)? -1.0: 1.0;
10563
10564 double min_d = 0.004; // ~= 40m at 10km
10565 int max_factor = 8;
10566 double r_max_factor = 0.125;
10567 if (!retreat)
10568 {
10570 {
10571 // much greater precision in combat
10572 if (max_flight_pitch > 1.0)
10573 {
10574 max_factor = floor(max_flight_pitch/0.125);
10575 r_max_factor = 1.0/max_factor;
10576 }
10577 min_d = 0.0004; // 10 times more precision ~= 4m at 10km
10578 max_factor *= 3;
10579 r_max_factor /= 3.0;
10580 }
10581 else if (accuracy >= COMBAT_AI_ISNT_AWFUL)
10582 {
10583 // slowly improve precision to target, but only if missing
10584 min_d -= 0.0001 * [self missedShots];
10585 if (min_d < 0.001)
10586 {
10587 min_d = 0.001;
10588 max_factor *= 2;
10589 r_max_factor /= 2.0;
10590 }
10591 }
10592 }
10593
10594 d_right = dot_product(relPos, v_right);
10595 d_up = dot_product(relPos, v_up);
10596 d_forward = dot_product(relPos, v_forward); // == cos of angle between v_forward and vector to target
10597
10598 if (d_forward * reverse > max_cos) // on_target!
10599 {
10600 return d_forward;
10601 }
10602
10603 // begin rule-of-thumb manoeuvres
10604 stick_pitch = 0.0;
10605 stick_roll = 0.0;
10606
10607
10608 if ((reverse * d_forward < -0.5) && !pitching_over) // we're going the wrong way!
10609 pitching_over = YES;
10610
10611 if (pitching_over)
10612 {
10613 if (reverse * d_up > 0) // pitch up
10615 else
10617 pitching_over = (reverse * d_forward < 0.707);
10618 }
10619
10620 // check if we are flying toward the destination..
10621 if ((d_forward < max_cos)||(retreat)) // not on course so we must adjust controls..
10622 {
10623 if (d_forward < -max_cos) // hack to avoid just flying away from the destination
10624 {
10625 d_up = min_d * 2.0;
10626 }
10627
10628 if (d_up > min_d)
10629 {
10630 int factor = sqrt(fabs(d_right) / fabs(min_d));
10631 if (factor > max_factor)
10632 factor = max_factor;
10633 if (d_right > min_d)
10634 stick_roll = - max_flight_roll * r_max_factor * factor; // note#
10635 if (d_right < -min_d)
10636 stick_roll = + max_flight_roll * r_max_factor * factor; // note#
10637 }
10638 if (d_up < -min_d)
10639 {
10640 int factor = sqrt(fabs(d_right) / fabs(min_d));
10641 if (factor > max_factor)
10642 factor = max_factor;
10643 if (d_right > min_d)
10644 stick_roll = + max_flight_roll * r_max_factor * factor; // note#
10645 if (d_right < -min_d)
10646 stick_roll = - max_flight_roll * r_max_factor * factor; // note#
10647 }
10648
10649 if (stick_roll == 0.0)
10650 {
10651 int factor = sqrt(fabs(d_up) / fabs(min_d));
10652 if (factor > max_factor)
10653 factor = max_factor;
10654 if (d_up > min_d)
10655 stick_pitch = - max_flight_pitch * reverse * r_max_factor * factor;
10656 if (d_up < -min_d)
10657 stick_pitch = + max_flight_pitch * reverse * r_max_factor * factor;
10658 }
10659
10661 {
10662 // don't overshoot target (helps accuracy at low frame rates)
10663 if (fabs(d_right) < fabs(stick_roll) * delta_t)
10664 {
10665 stick_roll = fabs(d_right) / delta_t * (stick_roll<0 ? -1 : 1);
10666 }
10667 if (fabs(d_up) < fabs(stick_pitch) * delta_t)
10668 {
10669 stick_pitch = fabs(d_up) / delta_t * (stick_pitch<0 ? -0.9 : 0.9);
10670 }
10671 }
10672
10673 }
10674 /* # note
10675 Eric 9-9-2010: Removed the "reverse" variable from the stick_roll calculation. This was mathematical wrong and
10676 made the ship roll in the wrong direction, preventing the ship to fly away in a straight line from the target.
10677 This means all the places were a jink was set, this jink never worked correctly. The main reason a ship still
10678 managed to turn at close range was probably by the fail-safe mechanisme with the "pitching_over" variable.
10679 The jink was programmed to do nothing within 500 meters of the ship and just fly away in direct line from the target
10680 in that range. Because of the bug the ships always rolled to the wrong side needed to fly away in direct line
10681 resulting in making it a difficult target.
10682 After fixing the bug, the ship realy flew away in direct line during the first 500 meters, making it a easy target
10683 for the player. All jink settings are retested and changed to give a turning behaviour that felt like the old
10684 situation, but now more deliberately set.
10685 */
10686
10687 // end rule-of-thumb manoeuvres
10688 stick_yaw = 0.0;
10689
10690 [self applySticks:delta_t];
10691
10692 if (retreat)
10693 d_forward *= d_forward; // make positive AND decrease granularity
10694
10695 if (d_forward < 0.0)
10696 return 0.0;
10697
10698 if ((!flightRoll)&&(!flightPitch)) // no correction
10699 return 1.0;
10700
10701 return d_forward;
10702}

◆ trackSideTarget:delta_t:

- (double) trackSideTarget: (double) 
delta_t: (BOOL)  leftside 

Definition at line 9589 of file ShipEntity.m.

10705 :(double) delta_t :(BOOL) leftside
10706{
10707 Entity* target = [self primaryTarget];
10708
10709 if (!target) // leave now!
10710 {
10711 [self noteLostTargetAndGoIdle]; // NOTE: was AI message: rather than reactToMessage:
10712 return 0.0;
10713 }
10714
10715 if (![self canStillTrackPrimaryTarget])
10716 {
10717 [self noteLostTargetAndGoIdle]; // NOTE: was AI message: rather than reactToMessage:
10718 return 0.0;
10719 }
10720
10721
10722 if (scanClass == CLASS_MISSILE) // never?
10723 return [self missileTrackPrimaryTarget: delta_t];
10724
10725 GLfloat d_forward, d_up, d_right;
10726
10727 Vector relPos = HPVectorToVector(HPvector_subtract([self calculateTargetPosition], position));
10728
10729
10730 if (!vector_equal(relPos, kZeroVector)) relPos = vector_normal(relPos);
10731 else relPos.z = 1.0;
10732
10733// worse shots with side lasers than fore/aft, in general
10734
10735 double max_cos = [self currentAimTolerance];
10736
10737 stick_roll = 0.0; //desired roll and pitch
10738 stick_pitch = 0.0;
10739 stick_yaw = 0.0;
10740
10741 double reverse = (leftside)? -1.0: 1.0;
10742
10743 double min_d = 0.004;
10745 {
10746 min_d = 0.002;
10747 }
10748 int max_factor = 8;
10749 double r_max_factor = 0.125;
10750
10751 d_right = dot_product(relPos, v_right);
10752 d_up = dot_product(relPos, v_up);
10753 d_forward = dot_product(relPos, v_forward); // == cos of angle between v_forward and vector to target
10754
10755 if (d_right * reverse > max_cos) // on_target!
10756 {
10757 return d_right * reverse;
10758 }
10759
10760 // begin rule-of-thumb manoeuvres
10761 stick_pitch = 0.0;
10762 stick_roll = 0.0;
10763 stick_yaw = 0.0;
10764
10765 // check if we are flying toward the destination..
10766 if ((d_right * reverse < max_cos)) // not on course so we must adjust controls..
10767 {
10768 if (d_right < -max_cos) // hack to avoid just pointing away from the destination
10769 {
10770 d_forward = min_d * 2.0;
10771 }
10772
10773 if (d_forward > min_d)
10774 {
10775 int factor = sqrt(fabs(d_up) / fabs(min_d));
10776 if (factor > max_factor)
10777 factor = max_factor;
10778 if (d_up > min_d)
10779 stick_pitch = + max_flight_pitch * r_max_factor * factor; // note#
10780 if (d_up < -min_d)
10781 stick_pitch = - max_flight_pitch * r_max_factor * factor; // note#
10782 }
10783 if (d_forward < -min_d)
10784 {
10785 int factor = sqrt(fabs(d_up) / fabs(min_d));
10786 if (factor > max_factor)
10787 factor = max_factor;
10788 if (d_up > min_d)
10789 stick_pitch = + max_flight_pitch * r_max_factor * factor; // note#
10790 if (d_up < -min_d)
10791 stick_pitch = - max_flight_pitch * r_max_factor * factor; // note#
10792 }
10793
10794 if (fabs(stick_pitch) == 0.0 || fabs(d_forward) > 0.5)
10795 {
10796 stick_pitch = 0.0;
10797 int factor = sqrt(fabs(d_forward) / fabs(min_d));
10798 if (factor > max_factor)
10799 factor = max_factor;
10800 if (d_forward > min_d)
10801 stick_yaw = - max_flight_yaw * reverse * r_max_factor * factor;
10802 if (d_forward < -min_d)
10803 {
10804 if (factor < max_factor/2.0) // compensate for forward thrust
10805 factor *= 2.0;
10806 stick_yaw = + max_flight_yaw * reverse * r_max_factor * factor;
10807 }
10808 }
10809 }
10810
10811
10812 // end rule-of-thumb manoeuvres
10813
10814 [self applySticks:delta_t];
10815
10816 if ((!flightPitch)&&(!flightYaw)) // no correction
10817 return 1.0;
10818
10819 return d_right * reverse;
10820}

◆ transitionToAegisNone

- (void) transitionToAegisNone

Definition at line 7408 of file ShipEntity.m.

7572{
7574 {
7575 Entity<OOStellarBody> *lastAegisLock = [self lastAegisLock];
7576 if (lastAegisLock != nil)
7577 {
7578 [self doScriptEvent:OOJSID("shipExitedPlanetaryVicinity") withArgument:lastAegisLock];
7579
7580 if (lastAegisLock == [UNIVERSE sun])
7581 {
7582 [shipAI message:@"AWAY_FROM_SUN"];
7583 }
7584 else
7585 {
7586 [shipAI message:@"AWAY_FROM_PLANET"];
7587 }
7588 }
7589
7591 {
7592 [shipAI message:@"AEGIS_NONE"];
7593 }
7594 }
7596}

◆ turretCount

- (NSUInteger) turretCount

Definition at line 6493 of file ShipEntity.m.

7026{
7027 NSUInteger count = 0;
7028 NSEnumerator *subEnum = [self shipSubEntityEnumerator];
7029 ShipEntity *se = nil;
7030 while ((se = [subEnum nextObject]))
7031 {
7032 if ([se isTurret])
7033 {
7034 count ++;
7035 }
7036 }
7037 return count;
7038}
BOOL isTurret()

Referenced by OOShipLibraryTurrets().

+ Here is the caller graph for this function:

◆ update:

- (void) update: (OOTimeDelta delta_t
implementation

Reimplemented from Entity.

Reimplemented in DockEntity, PlayerEntity, and StationEntity.

Definition at line 2092 of file ShipEntity.m.

2318 :(OOTimeDelta)delta_t
2319{
2320 if (shipinfoDictionary == nil)
2321 {
2322 OOLog(@"shipEntity.notDict", @"Ship %@ was not set up from dictionary.", self);
2323 [UNIVERSE removeEntity:self];
2324 return;
2325 }
2326
2327 if (!isfinite(maxFlightSpeed))
2328 {
2329 OOLog(@"ship.sanityCheck.failed", @"Ship %@ %@ infinite top speed, clamped to 300.", self, @"had");
2330 maxFlightSpeed = 300;
2331 }
2332
2333 bool isSubEnt = [self isSubEntity];
2334
2335 if (isDemoShip)
2336 {
2337 if (demoRate > 0)
2338 {
2339 OOScalar cos1 = cos(M_PI * ([UNIVERSE getTime] - demoStartTime) * demoRate / 11);
2340 OOScalar sin1 = sin(M_PI * ([UNIVERSE getTime] - demoStartTime) * demoRate / 11);
2341 OOScalar cos2 = cos(-M_PI * ([UNIVERSE getTime] - demoStartTime) * demoRate / 15);
2342 OOScalar sin2 = sin(-M_PI * ([UNIVERSE getTime] - demoStartTime) * demoRate / 15);
2343 Quaternion q1 = make_quaternion(cos1, sin1*sqrt(3)/2, sin1/2, 0);
2344 Quaternion q2 = make_quaternion(cos2, -sin2*sqrt(4)/sqrt(5), 0, sin2*sqrt(1)/sqrt(5));
2345 [self setOrientation: quaternion_multiply(q2, quaternion_multiply(q1, demoStartOrientation))];
2346 }
2347
2348 [super update:delta_t];
2349 if ([self subEntityCount] > 0)
2350 {
2351 // only copy the subent array if there are subentities
2352 ShipEntity *se = nil;
2353 foreach (se, [self subEntities])
2354 {
2355 [se update:delta_t];
2356 if ([se isShip])
2357 {
2358 BoundingBox sebb = [se findSubentityBoundingBox];
2359 bounding_box_add_vector(&totalBoundingBox, sebb.max);
2360 bounding_box_add_vector(&totalBoundingBox, sebb.min);
2361 }
2362 }
2363 }
2364 return;
2365 }
2366
2367
2368 if (!isSubEnt)
2369 {
2370 if (scanClass == CLASS_NOT_SET)
2371 {
2372 scanClass = CLASS_NEUTRAL;
2373 OOLog(@"ship.sanityCheck.failed", @"Ship %@ %@ with scanClass CLASS_NOT_SET; forced to CLASS_NEUTRAL.", self, [self primaryRole]);
2374 }
2375
2376 [self updateTrackingCurve];
2377
2378 //
2379 // deal with collisions
2380 //
2381 [self manageCollisions];
2382
2383 // subentity collisions managed via parent entity
2384
2385 //
2386 // reset any inadvertant legal mishaps
2387 //
2388 if (scanClass == CLASS_POLICE)
2389 {
2390 if (bounty > 0)
2391 {
2392 [self setBounty:0 withReason:kOOLegalStatusReasonPoliceAreClean];
2393 }
2394 ShipEntity* target = [self primaryTarget];
2395 if ((target)&&([target scanClass] == CLASS_POLICE))
2396 {
2397 [self noteLostTarget];
2398 }
2399 }
2400
2402 {
2403 // in checkCloseCollisionWith: we check if some thing has come within touch range (origin within our collision_radius)
2404 // here we check if it has gone outside that range
2405 NSString *other_key = nil;
2406
2407 // create a temp copy to iterate over, since we may want to
2408 // change the original
2409 NSDictionary *closeContactsTemp = [[NSDictionary alloc] initWithDictionary:closeContactsInfo];
2410 foreachkey (other_key, closeContactsTemp)
2411 {
2412 ShipEntity* other = [UNIVERSE entityForUniversalID:[other_key intValue]];
2413 if ((other != nil) && (other->isShip))
2414 {
2415 if (HPdistance2(position, other->position) > collision_radius * collision_radius) // moved beyond our sphere!
2416 {
2417 // calculate position with respect to our own position and orientation
2418 Vector dpos = HPVectorToVector(HPvector_between(position, other->position));
2419 Vector pos1 = make_vector(dot_product(dpos, v_right), dot_product(dpos, v_up), dot_product(dpos, v_forward));
2420 Vector pos0 = {0, 0, 0};
2421 ScanVectorFromString([closeContactsInfo objectForKey: other_key], &pos0);
2422 // send AI messages about the contact
2424 _primaryTarget = [other weakRetain];
2425 if ((pos0.x < 0.0)&&(pos1.x > 0.0))
2426 {
2427 [self doScriptEvent:OOJSID("shipTraversePositiveX") withArgument:other andReactToAIMessage:@"POSITIVE X TRAVERSE"];
2428 }
2429 if ((pos0.x > 0.0)&&(pos1.x < 0.0))
2430 {
2431 [self doScriptEvent:OOJSID("shipTraverseNegativeX") withArgument:other andReactToAIMessage:@"NEGATIVE X TRAVERSE"];
2432 }
2433 if ((pos0.y < 0.0)&&(pos1.y > 0.0))
2434 {
2435 [self doScriptEvent:OOJSID("shipTraversePositiveY") withArgument:other andReactToAIMessage:@"POSITIVE Y TRAVERSE"];
2436 }
2437 if ((pos0.y > 0.0)&&(pos1.y < 0.0))
2438 {
2439 [self doScriptEvent:OOJSID("shipTraverseNegativeY") withArgument:other andReactToAIMessage:@"NEGATIVE Y TRAVERSE"];
2440 }
2441 if ((pos0.z < 0.0)&&(pos1.z > 0.0))
2442 {
2443 [self doScriptEvent:OOJSID("shipTraversePositiveZ") withArgument:other andReactToAIMessage:@"POSITIVE Z TRAVERSE"];
2444 }
2445 if ((pos0.z > 0.0)&&(pos1.z < 0.0))
2446 {
2447 [self doScriptEvent:OOJSID("shipTraverseNegativeZ") withArgument:other andReactToAIMessage:@"NEGATIVE Z TRAVERSE"];
2448 }
2449 _primaryTarget = temp;
2450 [closeContactsInfo removeObjectForKey: other_key];
2451 }
2452 }
2453 else
2454 {
2455 [closeContactsInfo removeObjectForKey: other_key];
2456 }
2457 }
2458 [closeContactsTemp release];
2459 } // end if trackCloseContacts
2460
2461 } // end if !isSubEntity
2462
2463
2464#ifndef NDEBUG
2465 // DEBUGGING
2467 {
2468 OOLog(kOOLogEntityBehaviourChanged, @"%@ behaviour is now %@", self, OOStringFromBehaviour(behaviour));
2470 }
2471#endif
2472
2473 // cool all weapons.
2474 weapon_temp = fmaxf(weapon_temp - (float)(WEAPON_COOLING_FACTOR * delta_t), 0.0f);
2475 forward_weapon_temp = fmaxf(forward_weapon_temp - (float)(WEAPON_COOLING_FACTOR * delta_t), 0.0f);
2476 aft_weapon_temp = fmaxf(aft_weapon_temp - (float)(WEAPON_COOLING_FACTOR * delta_t), 0.0f);
2477 port_weapon_temp = fmaxf(port_weapon_temp - (float)(WEAPON_COOLING_FACTOR * delta_t), 0.0f);
2478 starboard_weapon_temp = fmaxf(starboard_weapon_temp - (float)(WEAPON_COOLING_FACTOR * delta_t), 0.0f);
2479
2480 // update time between shots
2481 shot_time += delta_t;
2482
2483 // handle radio message effects
2484 if (messageTime > 0.0)
2485 {
2486 messageTime -= delta_t;
2487 if (messageTime < 0.0) messageTime = 0.0;
2488 }
2489
2490 // temperature factors
2491 if(!isSubEnt)
2492 {
2493 double external_temp = 0.0;
2494 OOSunEntity *sun = [UNIVERSE sun];
2495 if (sun != nil)
2496 {
2497 // set the ambient temperature here
2498 double sun_zd = HPdistance2(position, [sun position]); // square of distance
2499 double sun_cr = sun->collision_radius;
2500 double alt1 = sun_cr * sun_cr / sun_zd;
2501 external_temp = SUN_TEMPERATURE * alt1;
2502 if ([sun goneNova]) external_temp *= 100;
2503
2504 if ([self hasFuelScoop] && alt1 > 0.75 && [self fuel] < [self fuelCapacity])
2505 {
2506 fuel_accumulator += (float)(delta_t * flightSpeed * 0.010 / [self fuelChargeRate]);
2507 // are we fast enough to collect any fuel?
2508 while (fuel_accumulator > 1.0f)
2509 {
2510 [self setFuel:[self fuel] + 1];
2511 fuel_accumulator -= 1.0f;
2512 [self doScriptEvent:OOJSID("shipScoopedFuel")];
2513 }
2514 }
2515 }
2516
2517 // work on the ship temperature
2518 //
2519 float heatThreshold = [self heatInsulation] * 100.0f;
2520 if (external_temp > heatThreshold && external_temp > ship_temperature)
2521 ship_temperature += (external_temp - ship_temperature) * delta_t * SHIP_INSULATION_FACTOR / [self heatInsulation];
2522 else
2523 {
2525 {
2526 ship_temperature += (external_temp - heatThreshold - ship_temperature) * delta_t * SHIP_COOLING_FACTOR / [self heatInsulation];
2528 }
2529 }
2530 }
2531 else //subents
2532 {
2533 ship_temperature = [[self owner] temperature];
2534 }
2535
2537 [self takeHeatDamage: delta_t * ship_temperature];
2538
2539 // are we burning due to low energy
2540 if ((energy < maxEnergy * 0.20)&&_showDamage) // prevents asteroid etc. from burning
2541 throw_sparks = YES;
2542
2543 // burning effects
2544 if (throw_sparks)
2545 {
2546 next_spark_time -= delta_t;
2547 if (next_spark_time < 0.0)
2548 {
2549 [self throwSparks];
2550 throw_sparks = NO; // until triggered again
2551 }
2552 }
2553
2554 if (!isSubEnt)
2555 {
2556
2557 // cloaking device
2558 if ([self hasCloakingDevice])
2559 {
2561 {
2564 {
2565 [self deactivateCloakingDevice];
2566 if (energy < 0) energy = 0;
2567 }
2568 }
2569 }
2570
2571 // military_jammer
2572 if ([self hasMilitaryJammer])
2573 {
2575 {
2578 {
2580 if (energy < 0) energy = 0;
2581 }
2582 }
2583 else
2584 {
2587 }
2588 }
2589
2590 // check outside factors
2591 /* aegis checks are expensive, so only do them once every km or so of flight
2592 * unlikely to be important otherwise. (every 100m if already close to
2593 * planet, to watch for surface)
2594
2595 * if have non-zero inertial velocity, need to check every frame,
2596 * as distanceTravelled does not include this component - CIM */
2597 if (_nextAegisCheck < distanceTravelled || !vector_equal([super velocity],kZeroVector))
2598 {
2599 aegis_status = [self checkForAegis]; // is a station or something nearby??
2600 if (aegis_status == AEGIS_NONE)
2601 {
2602 // in open space: check every km
2604 }
2605 else
2606 {
2607 // near planets: check every 100m
2609 }
2610 }
2611 } // end if !isSubEntity
2612
2613 // scripting
2615 {
2616 // When crashing into a boulder, STATUS_LAUNCHING is sometimes skipped on scooping the resulting splinters.
2617 OOEntityStatus status = [self status];
2618 if (script != nil && (status == STATUS_IN_FLIGHT ||
2619 status == STATUS_LAUNCHING ||
2620 status == STATUS_BEING_SCOOPED ||
2621 (status == STATUS_ACTIVE && self == [UNIVERSE station])
2622 ))
2623 {
2624 [PLAYER setScriptTarget:self];
2625 [self doScriptEvent:OOJSID("shipSpawned")];
2626 if ([self status] != STATUS_DEAD) [PLAYER doScriptEvent:OOJSID("shipSpawned") withArgument:self];
2627 }
2629 }
2630 /* No point in starting the AI if still launching */
2631 if (!haveStartedJSAI && [self status] != STATUS_LAUNCHING)
2632 {
2633 haveStartedJSAI = YES;
2634 [self doScriptEvent:OOJSID("aiStarted")];
2635 }
2636
2637 // behaviours according to status and behaviour
2638 //
2639 if ([self status] == STATUS_LAUNCHING)
2640 {
2641 if ([UNIVERSE getTime] > launch_time + launch_delay) // move for while before thinking
2642 {
2643 StationEntity *stationLaunchedFrom = [UNIVERSE nearestEntityMatchingPredicate:IsStationPredicate parameter:NULL relativeToEntity:self];
2644 [self setStatus:STATUS_IN_FLIGHT];
2645 // awaken JS-based AIs
2646 haveStartedJSAI = YES;
2647 [self doScriptEvent:OOJSID("aiStarted")];
2648 [self doScriptEvent:OOJSID("shipLaunchedFromStation") withArgument:stationLaunchedFrom];
2649 [shipAI reactToMessage:@"LAUNCHED OKAY" context:@"launched"];
2650 }
2651 else
2652 {
2653 // ignore behaviour just keep moving...
2654 flightYaw = 0.0;
2655 [self applyAttitudeChanges:delta_t];
2656 [self applyThrust:delta_t];
2657 if (energy < maxEnergy)
2658 {
2659 energy += energy_recharge_rate * delta_t;
2660 if (energy > maxEnergy)
2661 {
2662 energy = maxEnergy;
2663 [self doScriptEvent:OOJSID("shipEnergyBecameFull")];
2664 [shipAI message:@"ENERGY_FULL"];
2665 }
2666 }
2667
2668 if ([self subEntityCount] > 0)
2669 {
2670 // only copy the subent array if there are subentities
2671 ShipEntity *se = nil;
2672 foreach (se, [self subEntities])
2673 {
2674 [se update:delta_t];
2675 }
2676 }
2677 // super update
2678 [super update:delta_t];
2679
2680 return;
2681 }
2682 }
2683 //
2684 // double check scooped behaviour
2685 //
2686 if ([self status] == STATUS_BEING_SCOOPED)
2687 {
2688 //if we are being tractored, but we have no owner, then we have a problem
2689 if (behaviour != BEHAVIOUR_TRACTORED || [self owner] == nil || [self owner] == self || [self owner] == NO_TARGET)
2690 {
2691 // escaped tractor beam
2692 [self setStatus:STATUS_IN_FLIGHT]; // should correct 'uncollidable objects' bug
2693 behaviour = BEHAVIOUR_IDLE;
2694 frustration = 0.0;
2695 [self setOwner:self];
2696 [shipAI exitStateMachineWithMessage:nil]; // Escapepods and others should continue their old AI here.
2697 }
2698 }
2699
2700 if ([self status] == STATUS_COCKPIT_DISPLAY)
2701 {
2702 flightYaw = 0.0;
2703 [self applyAttitudeChanges:delta_t];
2704 GLfloat range2 = 0.1 * HPdistance2(position, _destination) / (collision_radius * collision_radius);
2705 if ((range2 > 1.0)||(velocity.z > 0.0)) range2 = 1.0;
2706 position = HPvector_add(position, vectorToHPVector(vector_multiply_scalar(velocity, range2 * delta_t)));
2707 }
2708 else
2709 {
2710 [self processBehaviour:delta_t];
2711
2712 // manage energy
2713 if (energy < maxEnergy)
2714 {
2715 energy += energy_recharge_rate * delta_t;
2716 if (energy > maxEnergy)
2717 {
2718 energy = maxEnergy;
2719 [self doScriptEvent:OOJSID("shipEnergyBecameFull")];
2720 [shipAI message:@"ENERGY_FULL"];
2721 }
2722 }
2723
2724 if (!isSubEnt)
2725 {
2726 // update destination position for escorts
2727 [self refreshEscortPositions];
2728 if ([self hasEscorts])
2729 {
2730 ShipEntity *escort = nil;
2731 unsigned i = 0;
2732 // Note: works on escortArray rather than escortEnumerator because escorts may be mutated.
2733 foreach (escort, [self escortArray])
2734 {
2735 [escort setEscortDestination:[self coordinatesForEscortPosition:i++]];
2736 }
2737
2738 ShipEntity *leader = [[self escortGroup] leader];
2739 if (leader != nil && ([leader scanClass] != [self scanClass])) {
2740 OOLog(@"ship.sanityCheck.failed", @"Ship %@ escorting %@ with wrong scanclass!", self, leader);
2741 [[self escortGroup] removeShip:self];
2742 [self setEscortGroup:nil];
2743 }
2744 }
2745 }
2746 }
2747
2748 // rotational velocity
2749 if (!quaternion_equal(subentityRotationalVelocity, kIdentityQuaternion) &&
2750 !quaternion_equal(subentityRotationalVelocity, kZeroQuaternion))
2751 {
2752 Quaternion qf = subentityRotationalVelocity;
2753 qf.w *= (1.0 - delta_t);
2754 qf.x *= delta_t;
2755 qf.y *= delta_t;
2756 qf.z *= delta_t;
2757 [self setOrientation:quaternion_multiply(qf, orientation)];
2758 }
2759
2760 // reset totalBoundingBox
2762
2763 // super update
2764 [super update:delta_t];
2765
2766 // update subentities
2767
2768 if ([self subEntityCount] > 0)
2769 {
2770 // only copy the subent array if there are subentities
2771 ShipEntity *se = nil;
2772 foreach (se, [self subEntities])
2773 {
2774 [se update:delta_t];
2775 if ([se isShip])
2776 {
2777 BoundingBox sebb = [se findSubentityBoundingBox];
2778 bounding_box_add_vector(&totalBoundingBox, sebb.max);
2779 bounding_box_add_vector(&totalBoundingBox, sebb.min);
2780 }
2781 }
2782 }
2783
2784 if (aiScriptWakeTime > 0 && [PLAYER clockTimeAdjusted] > aiScriptWakeTime)
2785 {
2786 aiScriptWakeTime = 0;
2787 [self doScriptEvent:OOJSID("aiAwoken")];
2788 }
2789}
const Quaternion kZeroQuaternion
BOOL ScanVectorFromString(NSString *xyzString, Vector *outVector)
#define SHIP_COOLING_FACTOR
Definition ShipEntity.h:61
#define CLOAKING_DEVICE_MIN_ENERGY
Definition ShipEntity.h:48
#define MILITARY_JAMMER_ENERGY_RATE
Definition ShipEntity.h:51
#define CLOAKING_DEVICE_ENERGY_RATE
Definition ShipEntity.h:47
#define WEAPON_COOLING_FACTOR
Definition ShipEntity.h:114
#define MILITARY_JAMMER_MIN_ENERGY
Definition ShipEntity.h:52
#define SUN_TEMPERATURE
Definition ShipEntity.h:72
#define SHIP_INSULATION_FACTOR
Definition ShipEntity.h:66
static NSString *const kOOLogEntityBehaviourChanged
Definition ShipEntity.m:101
GLfloat distanceTravelled
Definition Entity.h:136
BOOL hasFuelScoop()
void setEscortDestination:(HPVector dest)
void update:(OOTimeDelta delta_t)
GLfloat fuelChargeRate()
OOBehaviour debugLastBehaviour
Definition ShipEntity.h:427

◆ updateEscortFormation

- (void) updateEscortFormation

Definition at line 9589 of file ShipEntity.m.

13771{
13773}

◆ updateTrackingCurve

- (void) updateTrackingCurve

Definition at line 2092 of file ShipEntity.m.

6334{
6335 Entity *target = [self primaryTarget];
6336 OOTimeAbsolute now = [UNIVERSE getTime];
6337 if (target == nil || reactionTime <= 0.0 || trackingCurveTimes[0] + reactionTime/3.0 > now) return;
6341 if (EXPECT_NOT([target isShip] && [(ShipEntity *)target isCloaked]))
6342 {
6343 // if target is cloaked, introduce some more inaccuracy
6344 // 0.02 seems to be enough to give them slight difficulty on
6345 // a straight-line target and real trouble on anything better
6346 trackingCurvePositions[0] = HPvector_add([target position],OOHPVectorRandomSpatial([(ShipEntity *)target flightSpeed]*reactionTime*0.02));
6347 }
6348 else
6349 {
6350 trackingCurvePositions[0] = [target position];
6351 }
6355 trackingCurveTimes[0] = now;
6356 [self calculateTrackingCurve];
6357 return;
6358}

◆ upVector

- (Vector) upVector

Definition at line 14942 of file ShipEntity.m.

1278{
1279 return v_up;
1280}

◆ validateDefenseTargets

- (void) validateDefenseTargets

Definition at line 9589 of file ShipEntity.m.

11194{
11195 if (_defenseTargets == nil)
11196 {
11197 return;
11198 }
11199 // get enumerator from array as we'll be modifying original during enumeration
11200 NSEnumerator *defTargets = [[self allDefenseTargets] objectEnumerator];
11201 Entity *target = nil;
11202 while ((target = [[defTargets nextObject] weakRefUnderlyingObject]))
11203 {
11204 if ([target status] == STATUS_DEAD)
11205 {
11206 [self removeDefenseTarget:target];
11207 }
11208 }
11209}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ validForAddToUniverse

- (BOOL) validForAddToUniverse
implementation

Reimplemented from Entity.

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

2308{
2309 if (shipinfoDictionary == nil)
2310 {
2311 OOLog(@"shipEntity.notDict", @"Ship %@ was not set up from dictionary.", self);
2312 return NO;
2313 }
2314 return [super validForAddToUniverse];
2315}

◆ velocity

- (Vector) velocity
implementation

Reimplemented from Entity.

Definition at line 9589 of file ShipEntity.m.

12831{
12832 return vector_add([super velocity], [self thrustVector]);
12833}
Vector thrustVector()

◆ verifiedMissileTypeFromRole:

- (OOEquipmentType *) verifiedMissileTypeFromRole: (NSString *)  role
implementation

Definition at line 2092 of file ShipEntity.m.

3745 :(NSString *)role
3746{
3747 NSString *eqRole = nil;
3748 NSString *shipKey = nil;
3749 ShipEntity *missile = nil;
3750 OOEquipmentType *missileType = nil;
3751 BOOL isRandomMissile = [role isEqualToString:@"missile"];
3752
3753 if (isRandomMissile)
3754 {
3755 while (!shipKey)
3756 {
3757 shipKey = [UNIVERSE randomShipKeyForRoleRespectingConditions:role];
3758 if (!shipKey)
3759 {
3760 OOLogWARN(@"ship.setUp.missiles", @"%@ \"%@\" used in ship \"%@\" needs a valid %@.plist entry.%@", @"random missile", shipKey, [self name], @"shipdata", @"Trying another missile.");
3761 }
3762 }
3763 }
3764 else
3765 {
3766 shipKey = [UNIVERSE randomShipKeyForRoleRespectingConditions:role];
3767 if (!shipKey)
3768 {
3769 OOLogWARN(@"ship.setUp.missiles", @"%@ \"%@\" used in ship \"%@\" needs a valid %@.plist entry.%@", @"missile_role", role, [self name], @"shipdata", @" Using defaults instead.");
3770 return nil;
3771 }
3772 }
3773
3774 eqRole = [OOEquipmentType getMissileRegistryRoleForShip:shipKey]; // eqRole != role for generic missiles.
3775
3776 if (eqRole == nil)
3777 {
3778 missile = [UNIVERSE newShipWithName:shipKey];
3779 if (!missile)
3780 {
3781 if (isRandomMissile)
3782 OOLogWARN(@"ship.setUp.missiles", @"%@ \"%@\" used in ship \"%@\" needs a valid %@.plist entry.%@", @"random missile", shipKey, [self name], @"shipdata", @"Trying another missile.");
3783 else
3784 OOLogWARN(@"ship.setUp.missiles", @"%@ \"%@\" used in ship \"%@\" needs a valid %@.plist entry.%@", @"missile_role", role, [self name], @"shipdata", @" Using defaults instead.");
3785
3786 [OOEquipmentType setMissileRegistryRole:@"" forShip:shipKey]; // no valid role for this shipKey
3787 if (isRandomMissile) return [self verifiedMissileTypeFromRole:role];
3788 else return nil;
3789 }
3790
3791 if(isRandomMissile)
3792 {
3793 id value;
3794
3795 foreach (value, [[missile roleSet] roles])
3796 {
3797 role = (NSString *)value;
3798 missileType = [OOEquipmentType equipmentTypeWithIdentifier:role];
3799 // ensure that we have a missile or mine
3800 if ([missileType isMissileOrMine]) break;
3801 }
3802
3803 if (![missileType isMissileOrMine])
3804 {
3805 role = shipKey; // unique identifier to use in lieu of a valid equipment type if none are defined inside the generic missile roleset.
3806 }
3807 }
3808
3809 missileType = [OOEquipmentType equipmentTypeWithIdentifier:role];
3810
3811 if (!missileType)
3812 {
3813 OOLogWARN(@"ship.setUp.missiles", @"%@ \"%@\" used in ship \"%@\" needs a valid %@.plist entry.%@", (isRandomMissile ? @"random missile" : @"missile_role"), role, [self name], @"equipment", @" Enabling compatibility mode.");
3814 missileType = [self generateMissileEquipmentTypeFrom:role];
3815 }
3816
3818 [missile release];
3819 }
3820 else
3821 {
3822 if ([eqRole isEqualToString:@""])
3823 {
3824 // wrong ship definition, already written to the log in a previous call.
3825 if (isRandomMissile) return [self verifiedMissileTypeFromRole:role]; // try and find a valid missile with role 'missile'.
3826 return nil;
3827 }
3828 missileType = [OOEquipmentType equipmentTypeWithIdentifier:eqRole];
3829 }
3830
3831 return missileType;
3832}
void setMissileRegistryRole:forShip:(NSString *roles,[forShip] NSString *shipKey)
NSString * getMissileRegistryRoleForShip:(NSString *shipKey)

◆ volume

- (float) volume

Definition at line 14942 of file ShipEntity.m.

1437{
1438 return [octree volume];
1439}

◆ wasAddedToUniverse

- (void) wasAddedToUniverse
implementation

Reimplemented from Entity.

Definition at line 14942 of file ShipEntity.m.

1504{
1505 [super wasAddedToUniverse];
1506
1507 // if we have a universal id then we can proceed to set up any
1508 // stuff that happens when we get added to the UNIVERSE
1509 if (universalID != NO_TARGET)
1510 {
1511 // set up escorts
1512 if (([self status] == STATUS_IN_FLIGHT || [self status] == STATUS_LAUNCHING) && _pendingEscortCount != 0) // just popped into existence
1513 {
1514 [self setUpEscorts];
1515 }
1516 else
1517 {
1518 /* Earlier there was a silly log message here because I thought
1519 this would never happen, but wasn't entirely sure. Turns out
1520 it did!
1521 -- Ahruman 2009-09-13
1522 */
1524 }
1525 }
1526
1527 // Tell subentities, too
1528 [subEntities makeObjectsPerformSelector:@selector(wasAddedToUniverse)];
1529
1530 [self resetExhaustPlumes];
1531}

◆ wasRemovedFromUniverse

- (void) wasRemovedFromUniverse
implementation

Reimplemented from Entity.

Definition at line 14942 of file ShipEntity.m.

1535{
1536 [subEntities makeObjectsPerformSelector:@selector(wasRemovedFromUniverse)];
1537}

◆ weaponFacings

- (OOWeaponFacingSet) weaponFacings

Definition at line 2092 of file ShipEntity.m.

3247{
3248 return weapon_facings;
3249}

Referenced by OOShipLibraryWeapons().

+ Here is the caller graph for this function:

◆ weaponRange

- (GLfloat) weaponRange

◆ weaponRechargeRate

- (float) weaponRechargeRate

Definition at line 7408 of file ShipEntity.m.

7512{
7513 return weapon_recharge_rate;
7514}

◆ weaponRecoveryTime

- (GLfloat) weaponRecoveryTime

Definition at line 9589 of file ShipEntity.m.

9699{
9701 return OOClamp_0_1_f(result);
9702}

◆ weaponTypeForFacing:strict:

- (OOEquipmentType *) weaponTypeForFacing: (OOWeaponFacing facing
strict: (BOOL)  strict 

Reimplemented in PlayerEntity.

Definition at line 2092 of file ShipEntity.m.

3293 :(OOWeaponFacing)facing strict:(BOOL)strict
3294{
3295// OOWeaponType weaponType = [self weaponTypeIDForFacing:facing strict:strict];
3296// return [OOEquipmentType equipmentTypeWithIdentifier:OOEquipmentIdentifierFromWeaponType(weaponType)];
3297 return [self weaponTypeIDForFacing:facing strict:strict];
3298}

Referenced by ShipGetProperty().

+ Here is the caller graph for this function:

◆ weaponTypeIDForFacing:strict:

- (OOWeaponType) weaponTypeIDForFacing: (OOWeaponFacing facing
strict: (BOOL)  strict 

Definition at line 2092 of file ShipEntity.m.

3252 :(OOWeaponFacing)facing strict:(BOOL)strict
3253{
3254 OOWeaponType weaponType = nil;
3255
3256 if (facing & weapon_facings)
3257 {
3258 switch (facing)
3259 {
3261 weaponType = forward_weapon_type;
3262 // if no forward weapon, and not carrying out a strict check, see if subentities have forward weapons, return the first one found.
3263 if (isWeaponNone(weaponType) && !strict)
3264 {
3265 NSEnumerator *subEntEnum = [self shipSubEntityEnumerator];
3266 ShipEntity *subEntity = nil;
3267 while (isWeaponNone(weaponType) && (subEntity = [subEntEnum nextObject]))
3268 {
3269 weaponType = subEntity->forward_weapon_type;
3270 }
3271 }
3272 break;
3273
3274 case WEAPON_FACING_AFT:
3275 weaponType = aft_weapon_type;
3276 break;
3277
3278 case WEAPON_FACING_PORT:
3279 weaponType = port_weapon_type;
3280 break;
3281
3283 weaponType = starboard_weapon_type;
3284 break;
3285
3286 case WEAPON_FACING_NONE:
3287 break;
3288 }
3289 }
3290 return weaponType;
3291}

◆ witchspaceLeavingEffects

- (BOOL) witchspaceLeavingEffects

Definition at line 9589 of file ShipEntity.m.

13557{
13558 // all ships exiting witchspace will share the same orientation.
13559 orientation = [UNIVERSE getWitchspaceExitRotation];
13560 flightRoll = 0.0;
13561 stick_roll = 0.0;
13562 flightPitch = 0.0;
13563 stick_pitch = 0.0;
13564 flightYaw = 0.0;
13565 stick_yaw = 0.0;
13566 flightSpeed = 50.0; // constant speed same for all ships
13567// was a quarter of max speed, so the Anaconda speeds up and most
13568// others slow down - CIM
13569// will be overridden if left witchspace via a genuine wormhole
13571 if (![UNIVERSE addEntity:self]) // AI and status get initialised here
13572 {
13573 return NO;
13574 }
13575 [self setStatus:STATUS_EXITING_WITCHSPACE];
13576 [shipAI message:@"EXITED_WITCHSPACE"];
13577
13578 [UNIVERSE addWitchspaceJumpEffectForShip:self];
13579 [self setStatus:STATUS_IN_FLIGHT];
13580 return YES;
13581}

◆ withinStationAegis

- (BOOL) withinStationAegis

Definition at line 7616 of file ShipEntity.m.

7877{
7879}

◆ wormholeEntireGroup

- (void) wormholeEntireGroup

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

711{
712 [self wormholeGroup];
713 [self wormholeEscorts];
714}

◆ wormholeEscorts

- (void) wormholeEscorts

Provided by category ShipEntity(AI).

Definition at line 1 of file ShipEntityAI.m.

683{
684 ShipEntity *ship = nil;
685 NSString *context = nil;
686 WormholeEntity *whole = nil;
687
688 whole = [self primaryTarget];
689 if (![whole isWormhole]) return;
690
691#ifndef NDEBUG
692 context = [NSString stringWithFormat:@"%@ wormholeEscorts", [self shortDescription]];
693#endif
694
695 foreach (ship, [self escortEnumerator])
696 {
697 [ship addTarget:whole];
698 [ship reactToAIMessage:@"ENTER WORMHOLE" context:context];
699 [ship doScriptEvent:OOJSID("wormholeSuggested") withArgument:whole];
700 }
701
702 // We now have no escorts..
703
704 [_escortGroup release];
705 _escortGroup = nil;
706
707}

◆ wormholeGroup

- (void) wormholeGroup
implementation

Provided by category ShipEntity(PureAI).

Definition at line 1 of file ShipEntityAI.m.

1642{
1643 ShipEntity *ship = nil;
1644 WormholeEntity *whole = nil;
1645
1646 whole = [self primaryTarget];
1647 if (![whole isWormhole]) return;
1648
1649 foreach (ship, [[self group] mutationSafeEnumerator])
1650 {
1651 [ship addTarget:whole];
1652 [ship reactToAIMessage:@"ENTER WORMHOLE" context:@"wormholeGroup"];
1653 [ship doScriptEvent:OOJSID("wormholeSuggested") withArgument:whole];
1654 }
1655}

Member Data Documentation

◆ _beaconCode

- (NSString*) _beaconCode
private

Definition at line 484 of file ShipEntity.h.

◆ _beaconDrawable

- (id<OOHUDBeaconIcon>) _beaconDrawable
private

Definition at line 488 of file ShipEntity.h.

◆ _beaconLabel

- (NSString*) _beaconLabel
private

Definition at line 485 of file ShipEntity.h.

◆ _collisionExceptions

- (OOWeakSet*) _collisionExceptions
private

Definition at line 477 of file ShipEntity.h.

◆ _defenseTargets

- (OOWeakSet*) _defenseTargets
private

Definition at line 474 of file ShipEntity.h.

◆ _destination

- (HPVector) _destination

Definition at line 203 of file ShipEntity.h.

◆ _equipment

- (NSMutableArray*) _equipment
private

Definition at line 461 of file ShipEntity.h.

◆ _escortGroup

- (OOShipGroup*) _escortGroup
private

Definition at line 467 of file ShipEntity.h.

◆ _escortPositions

- (Vector _escortPositions[MAX_ESCORTS])
private

Definition at line 471 of file ShipEntity.h.

◆ _escortPositionsValid

- (BOOL) _escortPositionsValid
private

Definition at line 472 of file ShipEntity.h.

◆ _explicitlyUnpiloted

- (unsigned) _explicitlyUnpiloted
protected

Definition at line 274 of file ShipEntity.h.

◆ _foundTarget

- (OOWeakReference*) _foundTarget
protected

Definition at line 440 of file ShipEntity.h.

◆ _group

- (OOShipGroup*) _group
private

Definition at line 466 of file ShipEntity.h.

◆ _heatInsulation

- (float) _heatInsulation
private

Definition at line 462 of file ShipEntity.h.

◆ _lastAegisLock

- (OOWeakReference*) _lastAegisLock
private

Definition at line 464 of file ShipEntity.h.

◆ _lastEscortTarget

- (OOWeakReference*) _lastEscortTarget
protected

Definition at line 441 of file ShipEntity.h.

◆ _lightsActive

- (unsigned) _lightsActive
protected

Definition at line 282 of file ShipEntity.h.

◆ _maxEscortCount

- (uint8_t) _maxEscortCount
private

Definition at line 468 of file ShipEntity.h.

◆ _maxShipSubIdx

- (NSUInteger) _maxShipSubIdx
protected

Definition at line 343 of file ShipEntity.h.

◆ _missed_shots

- (int) _missed_shots
protected

Definition at line 376 of file ShipEntity.h.

◆ _missileRole

- (NSString*) _missileRole
protected

Definition at line 321 of file ShipEntity.h.

◆ _multiplyWeapons

- (BOOL) _multiplyWeapons
protected

Definition at line 391 of file ShipEntity.h.

◆ _nextAegisCheck

- (double) _nextAegisCheck
private

Definition at line 490 of file ShipEntity.h.

◆ _nextBeacon

- (OOWeakReference*) _nextBeacon
private

Definition at line 487 of file ShipEntity.h.

◆ _pendingEscortCount

- (uint8_t) _pendingEscortCount
private

Definition at line 469 of file ShipEntity.h.

◆ _prevBeacon

- (OOWeakReference*) _prevBeacon
private

Definition at line 486 of file ShipEntity.h.

◆ _primaryAggressor

- (OOWeakReference*) _primaryAggressor
protected

Definition at line 438 of file ShipEntity.h.

◆ _primaryTarget

- (OOWeakReference*) _primaryTarget
protected

Definition at line 437 of file ShipEntity.h.

◆ _profileRadius

- (GLfloat) _profileRadius
private

Definition at line 479 of file ShipEntity.h.

◆ _proximityAlert

- (OOWeakReference*) _proximityAlert
protected

Definition at line 444 of file ShipEntity.h.

◆ _rememberedShip

- (OOWeakReference*) _rememberedShip
protected

Definition at line 443 of file ShipEntity.h.

◆ _scaleFactor

- (GLfloat) _scaleFactor
protected

Definition at line 388 of file ShipEntity.h.

◆ _scriptedMisjumpRange

- (GLfloat) _scriptedMisjumpRange
protected

Definition at line 284 of file ShipEntity.h.

◆ _shipHitByLaser

- (OOWeakReference*) _shipHitByLaser
private

Definition at line 481 of file ShipEntity.h.

◆ _shipKey

- (NSString*) _shipKey
private

Definition at line 459 of file ShipEntity.h.

◆ _showDamage

- (unsigned) _showDamage
protected

Definition at line 270 of file ShipEntity.h.

◆ _subEntityTakingDamage

- (OOWeakReference*) _subEntityTakingDamage
private

Definition at line 457 of file ShipEntity.h.

◆ _subIdx

- (NSUInteger) _subIdx
protected

Definition at line 342 of file ShipEntity.h.

◆ _targetStation

- (OOWeakReference*) _targetStation
protected

Definition at line 439 of file ShipEntity.h.

◆ _thankedShip

- (OOWeakReference*) _thankedShip
protected

Definition at line 442 of file ShipEntity.h.

◆ accuracy

- (GLfloat) accuracy
protected

Definition at line 373 of file ShipEntity.h.

◆ aegis_status

- (OOAegisStatus) aegis_status
protected

Definition at line 378 of file ShipEntity.h.

◆ aft_weapon_temp

- (GLfloat) aft_weapon_temp
protected

Definition at line 315 of file ShipEntity.h.

◆ aft_weapon_type

- (OOWeaponType) aft_weapon_type
protected

Definition at line 306 of file ShipEntity.h.

◆ afterburner_rate

- (GLfloat) afterburner_rate
protected

Definition at line 291 of file ShipEntity.h.

◆ afterburner_speed_factor

- (GLfloat) afterburner_speed_factor
protected

Definition at line 292 of file ShipEntity.h.

◆ aftWeaponOffset

- (NSArray *) aftWeaponOffset
protected

Definition at line 394 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ aim_tolerance

- (GLfloat) aim_tolerance
protected

Definition at line 375 of file ShipEntity.h.

◆ aiScript

- (OOJSScript*) aiScript
protected

Definition at line 223 of file ShipEntity.h.

◆ aiScriptWakeTime

- (OOTimeAbsolute) aiScriptWakeTime
protected

Definition at line 224 of file ShipEntity.h.

◆ behaviour

- (OOBehaviour) behaviour

Definition at line 211 of file ShipEntity.h.

◆ being_fined

- (unsigned) being_fined
protected

Definition at line 259 of file ShipEntity.h.

◆ being_mined

- (unsigned) being_mined
protected

Definition at line 257 of file ShipEntity.h.

◆ bounty

- (OOCreditsQuantity) bounty
protected

Definition at line 300 of file ShipEntity.h.

◆ canFragment

- (unsigned) canFragment
protected

Definition at line 268 of file ShipEntity.h.

◆ cargo

- (NSMutableArray *) cargo
protected

Definition at line 361 of file ShipEntity.h.

◆ cargo_dump_time

- (OOTimeAbsolute) cargo_dump_time
protected

Definition at line 358 of file ShipEntity.h.

◆ cargo_flag

- (OOCargoFlag) cargo_flag
protected

Definition at line 299 of file ShipEntity.h.

◆ cargo_type

- (OOCargoType) cargo_type
protected

Definition at line 298 of file ShipEntity.h.

◆ cloakAutomatic

- (unsigned) cloakAutomatic
protected

Definition at line 267 of file ShipEntity.h.

◆ cloaking_device_active

- (unsigned) cloaking_device_active
protected

Definition at line 265 of file ShipEntity.h.

◆ cloakPassive

- (BOOL) cloakPassive
protected

Provided by category ShipEntity(Private).

Definition at line 266 of file ShipEntity.h.

◆ closeContactsInfo

- (NSMutableDictionary*) closeContactsInfo
protected

Definition at line 402 of file ShipEntity.h.

◆ collision_vector

- (Vector) collision_vector
protected

Definition at line 386 of file ShipEntity.h.

◆ commodity_amount

- (OOCargoQuantity) commodity_amount
protected

Definition at line 364 of file ShipEntity.h.

◆ commodity_type

- (OOCommodityType) commodity_type
protected

Definition at line 363 of file ShipEntity.h.

◆ coordinates

- (HPVector) coordinates
protected

Definition at line 339 of file ShipEntity.h.

◆ crew

- (NSArray *) crew
protected

Definition at line 399 of file ShipEntity.h.

◆ cruiseSpeed

- (double) cruiseSpeed
protected

Definition at line 243 of file ShipEntity.h.

◆ currentWeaponFacing

- (OOWeaponFacing) currentWeaponFacing
protected

◆ debugLastBehaviour

- (OOBehaviour) debugLastBehaviour
protected

Definition at line 427 of file ShipEntity.h.

◆ default_laser_color

- (OOColor*) default_laser_color
protected

Definition at line 230 of file ShipEntity.h.

◆ demoRate

- (OOScalar) demoRate
private

Definition at line 494 of file ShipEntity.h.

◆ demoStartOrientation

- (Quaternion) demoStartOrientation
private

Definition at line 496 of file ShipEntity.h.

◆ demoStartTime

- (OOTimeAbsolute) demoStartTime
private

Definition at line 495 of file ShipEntity.h.

◆ desired_range

- (GLfloat) desired_range

Definition at line 205 of file ShipEntity.h.

◆ desired_speed

- (GLfloat) desired_speed

Definition at line 206 of file ShipEntity.h.

◆ destination_system

- (OOSystemID) destination_system
protected

Definition at line 380 of file ShipEntity.h.

◆ displayName

- (NSString *) displayName
protected

Definition at line 330 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ distance2_scanned_ships

- (GLfloat distance2_scanned_ships[MAX_SCAN_NUMBER+1])
protected

Definition at line 414 of file ShipEntity.h.

◆ docking_match_rotation

- (unsigned) docking_match_rotation
protected

Definition at line 251 of file ShipEntity.h.

◆ dockingInstructions

- (NSDictionary *) dockingInstructions
protected

Definition at line 227 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ energy_recharge_rate

- (GLfloat) energy_recharge_rate
protected

Definition at line 302 of file ShipEntity.h.

◆ entity_personality

- (uint16_t) entity_personality
protected

Definition at line 430 of file ShipEntity.h.

◆ equipment_weight

- (OOCargoQuantity) equipment_weight
protected

Definition at line 297 of file ShipEntity.h.

◆ exhaust_emissive_color

- (OOColor*) exhaust_emissive_color
protected

Definition at line 231 of file ShipEntity.h.

◆ explosionType

- (NSArray*) explosionType
protected

Definition at line 335 of file ShipEntity.h.

◆ extra_cargo

- (OOCargoQuantity) extra_cargo
protected

Definition at line 296 of file ShipEntity.h.

◆ flightPitch

- (GLfloat) flightPitch
protected

Definition at line 370 of file ShipEntity.h.

Referenced by PlayerShipSetProperty().

◆ flightRoll

- (GLfloat) flightRoll
protected

Definition at line 369 of file ShipEntity.h.

Referenced by PlayerShipSetProperty().

◆ flightSpeed

- (GLfloat) flightSpeed
protected

Definition at line 368 of file ShipEntity.h.

◆ flightYaw

- (GLfloat) flightYaw
protected

Definition at line 371 of file ShipEntity.h.

Referenced by PlayerShipSetProperty().

◆ forward_weapon_temp

- (GLfloat) forward_weapon_temp
protected

Definition at line 315 of file ShipEntity.h.

◆ forward_weapon_type

- (OOWeaponType) forward_weapon_type
protected

Definition at line 305 of file ShipEntity.h.

◆ forwardWeaponOffset

- (NSArray *) forwardWeaponOffset
protected

Definition at line 393 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ frustration

- (double) frustration
protected

Definition at line 348 of file ShipEntity.h.

◆ fuel

- (OOFuelQuantity) fuel
protected

Definition at line 288 of file ShipEntity.h.

◆ fuel_accumulator

- (GLfloat) fuel_accumulator
protected

Definition at line 289 of file ShipEntity.h.

◆ hasScoopMessage

- (unsigned) hasScoopMessage
protected

Definition at line 275 of file ShipEntity.h.

◆ haveExecutedSpawnAction

- (unsigned) haveExecutedSpawnAction
protected

Definition at line 279 of file ShipEntity.h.

◆ haveStartedJSAI

- (unsigned) haveStartedJSAI
protected

Definition at line 280 of file ShipEntity.h.

◆ home_system

- (OOSystemID) home_system
protected

Definition at line 379 of file ShipEntity.h.

◆ hyperspaceMotorSpinTime

- (float) hyperspaceMotorSpinTime
protected

Definition at line 247 of file ShipEntity.h.

◆ isDemoShip

- (BOOL) isDemoShip
private

Definition at line 493 of file ShipEntity.h.

◆ isFrangible

- (BOOL) isFrangible
protected

Definition at line 264 of file ShipEntity.h.

◆ isHulk

- (BOOL) isHulk
protected

Definition at line 261 of file ShipEntity.h.

◆ isMissile

- (BOOL) isMissile
protected

Definition at line 273 of file ShipEntity.h.

◆ isNearPlanetSurface

- (unsigned) isNearPlanetSurface
protected

Definition at line 263 of file ShipEntity.h.

◆ isWreckage

- (unsigned) isWreckage
protected

Definition at line 269 of file ShipEntity.h.

◆ jink

- (Vector) jink
protected

Definition at line 338 of file ShipEntity.h.

◆ laser_color

- (OOColor*) laser_color
protected

Definition at line 229 of file ShipEntity.h.

◆ last_shot_time

- (OOTimeAbsolute) last_shot_time
protected

Definition at line 359 of file ShipEntity.h.

◆ lastRadioMessage

- (NSString*) lastRadioMessage
protected

Definition at line 404 of file ShipEntity.h.

◆ launch_delay

- (double) launch_delay
protected

Definition at line 345 of file ShipEntity.h.

◆ launch_time

- (double) launch_time
protected

Definition at line 344 of file ShipEntity.h.

◆ likely_cargo

- (OOCargoQuantity) likely_cargo
protected

Definition at line 294 of file ShipEntity.h.

◆ max_cargo

- (OOCargoQuantity) max_cargo
protected

Definition at line 295 of file ShipEntity.h.

◆ max_flight_pitch

- (GLfloat) max_flight_pitch
protected

Definition at line 241 of file ShipEntity.h.

◆ max_flight_roll

- (GLfloat) max_flight_roll
protected

Definition at line 240 of file ShipEntity.h.

◆ max_flight_yaw

- (GLfloat) max_flight_yaw
protected

Definition at line 242 of file ShipEntity.h.

◆ max_missiles

- (unsigned) max_missiles
protected

Definition at line 320 of file ShipEntity.h.

◆ max_thrust

- (GLfloat) max_thrust
protected

Definition at line 245 of file ShipEntity.h.

◆ maxFlightSpeed

- (GLfloat) maxFlightSpeed
protected

Definition at line 239 of file ShipEntity.h.

Referenced by OOShipLibrarySpeed().

◆ messageTime

- (double) messageTime
protected

Definition at line 382 of file ShipEntity.h.

◆ military_jammer_active

- (unsigned) military_jammer_active
protected

Definition at line 249 of file ShipEntity.h.

◆ missile_launch_time

- (OOTimeAbsolute) missile_launch_time
protected

Definition at line 323 of file ShipEntity.h.

◆ missile_list

- (OOEquipmentType* missile_list[SHIPENTITY_MAX_MISSILES])
protected

Definition at line 434 of file ShipEntity.h.

◆ missile_load_time

- (OOTimeDelta) missile_load_time
protected

Definition at line 322 of file ShipEntity.h.

◆ missiles

- (unsigned) missiles
protected

Definition at line 319 of file ShipEntity.h.

◆ n_scanned_ships

- (unsigned) n_scanned_ships
protected

Definition at line 415 of file ShipEntity.h.

◆ name

- (NSString *) name
protected

Definition at line 327 of file ShipEntity.h.

Referenced by ShipGetProperty(), and ShipRunLegacyScriptActions().

◆ navpoints

- (HPVector navpoints[32])
protected

Definition at line 418 of file ShipEntity.h.

◆ next_navpoint_index

- (unsigned) next_navpoint_index
protected

Definition at line 419 of file ShipEntity.h.

◆ next_spark_time

- (double) next_spark_time
protected

Definition at line 384 of file ShipEntity.h.

◆ noRocks

- (unsigned) noRocks
protected

Definition at line 281 of file ShipEntity.h.

◆ number_of_navpoints

- (unsigned) number_of_navpoints
protected

Definition at line 420 of file ShipEntity.h.

◆ octree

- (Octree *) octree
protected

Definition at line 423 of file ShipEntity.h.

Referenced by absoluteIJKForSubentity.

◆ patrol_counter

- (int) patrol_counter
protected

Definition at line 351 of file ShipEntity.h.

◆ pitch_tolerance

- (GLfloat) pitch_tolerance
protected

Definition at line 374 of file ShipEntity.h.

◆ pitching_over

- (unsigned) pitching_over
protected

Definition at line 253 of file ShipEntity.h.

◆ planetForLanding

- (OOUniversalID) planetForLanding
protected

Definition at line 346 of file ShipEntity.h.

◆ port_weapon_temp

- (GLfloat) port_weapon_temp
protected

Definition at line 315 of file ShipEntity.h.

◆ port_weapon_type

- (OOWeaponType) port_weapon_type
protected

Definition at line 307 of file ShipEntity.h.

◆ portWeaponOffset

- (NSArray *) portWeaponOffset
protected

Definition at line 395 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ previousCondition

- (NSMutableDictionary*) previousCondition
protected

Definition at line 353 of file ShipEntity.h.

◆ primaryRole

- (NSString *) primaryRole
protected

Definition at line 333 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ reactionTime

- (float) reactionTime
protected

Definition at line 449 of file ShipEntity.h.

◆ reference

- (Vector) reference
protected

Definition at line 340 of file ShipEntity.h.

◆ reportAIMessages

- (BOOL) reportAIMessages
protected

Definition at line 255 of file ShipEntity.h.

Referenced by AI::clearAllData.

◆ roleSet

- (OORoleSet *) roleSet
protected

Definition at line 332 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ rolling_over

- (unsigned) rolling_over
protected

Definition at line 254 of file ShipEntity.h.

◆ scan_description

- (NSString*) scan_description
protected

Definition at line 331 of file ShipEntity.h.

◆ scanned_ships

- (ShipEntity* scanned_ships[MAX_SCAN_NUMBER+1])
protected

Definition at line 413 of file ShipEntity.h.

◆ scanner_display_color1

- (OOColor*) scanner_display_color1
protected

Definition at line 232 of file ShipEntity.h.

◆ scanner_display_color2

- (OOColor*) scanner_display_color2
protected

Definition at line 233 of file ShipEntity.h.

◆ scanner_display_color_hostile1

- (OOColor*) scanner_display_color_hostile1
protected

Definition at line 234 of file ShipEntity.h.

◆ scanner_display_color_hostile2

- (OOColor*) scanner_display_color_hostile2
protected

Definition at line 235 of file ShipEntity.h.

◆ scannerRange

- (GLfloat) scannerRange
protected

Definition at line 317 of file ShipEntity.h.

◆ script

- (OOJSScript *) script
protected

Definition at line 222 of file ShipEntity.h.

◆ scripted_misjump

- (unsigned) scripted_misjump
protected

Definition at line 278 of file ShipEntity.h.

◆ scriptInfo

- (NSDictionary *) scriptInfo
protected

Definition at line 431 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ ship_temperature

- (float) ship_temperature
protected

Definition at line 410 of file ShipEntity.h.

◆ shipAI

- (AI*) shipAI
protected

Definition at line 325 of file ShipEntity.h.

◆ shipClassName

- (NSString *) shipClassName
protected

Definition at line 329 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ shipinfoDictionary

- (NSDictionary*) shipinfoDictionary
protected

Definition at line 217 of file ShipEntity.h.

◆ shipUniqueName

- (NSString *) shipUniqueName
protected

Definition at line 328 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ shot_counter

- (int) shot_counter
protected

Definition at line 357 of file ShipEntity.h.

◆ shot_time

- (OOTimeDelta) shot_time

Definition at line 197 of file ShipEntity.h.

◆ starboard_weapon_temp

- (GLfloat) starboard_weapon_temp
protected

Definition at line 315 of file ShipEntity.h.

◆ starboard_weapon_type

- (OOWeaponType) starboard_weapon_type
protected

Definition at line 308 of file ShipEntity.h.

◆ starboardWeaponOffset

- (NSArray *) starboardWeaponOffset
protected

Definition at line 396 of file ShipEntity.h.

Referenced by ShipGetProperty().

◆ stick_pitch

- (GLfloat) stick_pitch

Definition at line 209 of file ShipEntity.h.

◆ stick_roll

- (GLfloat) stick_roll

Definition at line 208 of file ShipEntity.h.

◆ stick_yaw

- (GLfloat) stick_yaw

Definition at line 210 of file ShipEntity.h.

◆ subEntities

- (NSArray *) subEntities
protected

Definition at line 433 of file ShipEntity.h.

Referenced by absoluteIJKForSubentity.

◆ subentityRotationalVelocity

- (Quaternion) subentityRotationalVelocity
protected

Definition at line 219 of file ShipEntity.h.

◆ success_factor

- (GLfloat) success_factor
protected

Definition at line 349 of file ShipEntity.h.

◆ sunGlareFilter

- (GLfloat) sunGlareFilter
protected

Definition at line 286 of file ShipEntity.h.

◆ suppressAegisMessages

- (unsigned) suppressAegisMessages
protected

Definition at line 272 of file ShipEntity.h.

◆ suppressExplosion

- (unsigned) suppressExplosion
protected

Definition at line 271 of file ShipEntity.h.

◆ thrust

- (float) thrust
protected

Definition at line 246 of file ShipEntity.h.

◆ totalBoundingBox

- (BoundingBox) totalBoundingBox

Definition at line 213 of file ShipEntity.h.

Referenced by OOShipLibrarySize(), and ShipGetProperty().

◆ trackCloseContacts

- (BOOL) trackCloseContacts
protected

Definition at line 262 of file ShipEntity.h.

◆ trackingCurveCoeffs

- (HPVector trackingCurveCoeffs[3])
protected

Definition at line 452 of file ShipEntity.h.

◆ trackingCurvePositions

- (HPVector trackingCurvePositions[4])
protected

Definition at line 450 of file ShipEntity.h.

◆ trackingCurveTimes

- (OOTimeAbsolute trackingCurveTimes[4])
protected

Definition at line 451 of file ShipEntity.h.

◆ tractor_position

- (Vector) tractor_position
protected

Definition at line 407 of file ShipEntity.h.

◆ v_forward

- (Vector) v_forward

Definition at line 200 of file ShipEntity.h.

◆ v_right

- (Vector) v_right

Definition at line 200 of file ShipEntity.h.

◆ v_up

- (Vector) v_up

Definition at line 200 of file ShipEntity.h.

◆ weapon_damage

- (GLfloat) weapon_damage
protected

Definition at line 309 of file ShipEntity.h.

◆ weapon_damage_override

- (GLfloat) weapon_damage_override
protected

Definition at line 310 of file ShipEntity.h.

◆ weapon_energy_use

- (GLfloat) weapon_energy_use
protected

Definition at line 314 of file ShipEntity.h.

◆ weapon_facings

- (OOWeaponFacingSet) weapon_facings
protected

Definition at line 304 of file ShipEntity.h.

◆ weapon_recharge_rate

- (float) weapon_recharge_rate
protected

Definition at line 356 of file ShipEntity.h.

◆ weapon_shot_temperature

- (GLfloat) weapon_shot_temperature
protected

Definition at line 314 of file ShipEntity.h.

◆ weapon_temp

- (GLfloat) weapon_temp
protected

Definition at line 314 of file ShipEntity.h.

◆ weaponRange

- (GLfloat) weaponRange
protected

Definition at line 311 of file ShipEntity.h.

Referenced by OOLaserShotEntity::dealloc.


The documentation for this class was generated from the following files: