AddShips Part I:

* new js methods added system.addShips(), system.addGroup(), system.addShipsToRoute(), system.addGroupToRoute() if a ship is created near the witchpoint, it gets the witchspace rings, and its status is STATUS_LAUNCHING, otherwise it's STATUS_IN_FLIGHT, and no witchspace effect.
* tentatively fixed berlios bug #14626: 'AI is initialised twice since 1.71'
when entities are added to the universe, the AI state is set to GLOBAL only once after their ID is set. Seems to work.

- reworked witchpoint buoy to use multiple colour flashers.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@2888 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Marc 2009-12-17 06:25:41 +00:00
parent 0acbfc4d64
commit b6826f47bc
13 changed files with 540 additions and 248 deletions

View File

@ -819,8 +819,26 @@
name = "Witchpoint Beacon";
roles = "buoy-witchpoint";
subentities = (
"*FLASHER* 0 0 60 60 0.15 1 150",
{
type = "flasher";
position = (0, 0, 60);
frequency = 0.15;
phase = 1;
size = 150;
colors = ({hue = 60;},{ hue = 30;},{ hue = 30; saturation = 0; brightness = 0.9});
},
{
type = "flasher";
position = (0, 0, -60);
frequency = 0.15;
phase = -1;
size = 150;
colors = ({ hue = 30; saturation = 0; brightness = 0.9},{ hue = 60;},{hue = 30;});
},
/* Old flashers. Replaced by the multicolour ones above.
"*FLASHER* 0 0 60 60 0.15 1 150",
"*FLASHER* 0 0 -60 30 0.15 0.0 150",
*/
"*FLASHER* 0 0 60 5 2 0.0 25",
"*FLASHER* 0 0 -60 5 2 0.0 25"
);

View File

@ -33,6 +33,7 @@ MA 02110-1301, USA.
#import "AI.h"
#import "Universe.h"
#import "ShipEntity.h"
#import "ShipEntityAI.h"
#import "OOCharacter.h"
#import "OOMaths.h"
@ -440,15 +441,13 @@ static OOColor *ColorWithHSBColorAndAlpha(Vector c, float a)
[shuttle_ship setScanClass: CLASS_NEUTRAL];
[shuttle_ship setCargoFlag:CARGO_FLAG_FULL_PLENTIFUL];
[shuttle_ship setStatus:STATUS_IN_FLIGHT];
//[shuttle_ship setStatus:STATUS_IN_FLIGHT];
[shuttle_ship switchAITo:@"risingShuttleAI.plist"];
[UNIVERSE addEntity:shuttle_ship];
[[shuttle_ship getAI] setStateMachine:@"risingShuttleAI.plist"]; // must happen after adding to the universe!
[shuttle_ship release];
_shuttlesOnGround--;
_lastLaunchTime = [UNIVERSE getTime];
[shuttle_ship release];
}
}

View File

@ -1350,13 +1350,10 @@ double longitudeFromVector(Vector v);
[shuttle_ship setOrientation:q1];
[shuttle_ship setScanClass: CLASS_NEUTRAL];
[shuttle_ship setCargoFlag:CARGO_FLAG_FULL_PLENTIFUL];
[shuttle_ship setStatus:STATUS_IN_FLIGHT];
//[shuttle_ship setStatus:STATUS_IN_FLIGHT];
[shuttle_ship switchAITo:@"risingShuttleAI.plist"];
[UNIVERSE addEntity:shuttle_ship];
[[shuttle_ship getAI] setStateMachine:@"risingShuttleAI.plist"]; // must happen after adding to the universe!
[shuttle_ship release];
}

View File

@ -41,6 +41,7 @@ MA 02110-1301, USA.
#import "ResourceManager.h"
#import "Universe.h"
#import "AI.h"
#import "ShipEntityAI.h"
#import "MyOpenGLView.h"
#import "OOTrumble.h"
#import "PlayerEntityLoadSave.h"
@ -2978,18 +2979,18 @@ static PlayerEntity *sSharedPlayer = nil;
{
if (!mine)
return nil;
[mine setOwner: self];
[mine setBehaviour: BEHAVIOUR_IDLE];
[self dumpItem: mine]; // includes UNIVERSE addEntity - starts the timer !!!!
[mine setScanClass: CLASS_MINE];
float mine_speed = 500.0f;
[self dumpItem: mine];
Vector mvel = [mine velocity];
mvel.x -= mine_speed * v_forward.x;
mvel.y -= mine_speed * v_forward.y;
mvel.z -= mine_speed * v_forward.z;
[mine setVelocity: mvel];
[mine setScanClass: CLASS_MINE];
[mine setStatus: STATUS_IN_FLIGHT];
[mine setBehaviour: BEHAVIOUR_IDLE];
[mine setOwner: self];
[[mine getAI] setState:@"GLOBAL"]; // start the timer !!!!
//[[mine getAI] setState:@"GLOBAL"]; // start the timer !!!!
return mine;
}
@ -3428,15 +3429,12 @@ static PlayerEntity *sSharedPlayer = nil;
[doppelganger setRoll:0.2 * (randf() - 0.5)];
[doppelganger setDesiredSpeed:flightSpeed];
[doppelganger setOwner:self];
[doppelganger setStatus:STATUS_IN_FLIGHT]; // necessary to get it going!
//[doppelganger setStatus:STATUS_IN_FLIGHT];
[doppelganger setBehaviour:BEHAVIOUR_IDLE];
[doppelganger switchAITo:@"nullAI.plist"]; // fly straight on
[UNIVERSE addEntity:doppelganger];
[[doppelganger getAI] setStateMachine:@"nullAI.plist"]; // fly straight on
result = [doppelganger universalID];
[doppelganger release]; //release
}
@ -4190,12 +4188,11 @@ static PlayerEntity *sSharedPlayer = nil;
- (void) leaveWitchspace
{
float d1 = (float)(SCANNER_MAX_RANGE*((ranrot_rand() % 256)/256.0 - 0.5));
Vector pos = [UNIVERSE getWitchspaceExitPosition];
Quaternion q_rtn = [UNIVERSE getWitchspaceExitRotation];
Quaternion q1;
quaternion_set_random(&q1);
float d1 = (float)(SCANNER_MAX_RANGE*((ranrot_rand() % 256)/256.0 - 0.5));
if (abs((int)d1) < 750)
{// no closer than 750m. Eric, was original 500m but that collides with some buoy variants.
d1 += ((d1 > 0.0)? 750.0f: -750.0f);
@ -4206,7 +4203,7 @@ static PlayerEntity *sSharedPlayer = nil;
pos.z += v1.z * d1;
position = pos;
orientation = q_rtn;
orientation = [UNIVERSE getWitchspaceExitRotation];
flightRoll = 0.0f;
flightPitch = 0.0f;
flightYaw = 0.0f;

View File

@ -1420,16 +1420,15 @@ static NSMutableDictionary* currentShipyard = nil;
[ship setOrientation: q2];
[ship setPositionX:1.2 * cr y:0.8 * cr z:6.4 * cr];
[ship setStatus: STATUS_COCKPIT_DISPLAY];
[ship setScanClass: CLASS_NO_DRAW];
[ship setRoll: M_PI/10.0];
[ship setPitch: M_PI/25.0];
if([ship pendingEscortCount] > 0) [ship setPendingEscortCount:0];
[UNIVERSE addEntity: ship];
[[ship getAI] setStateMachine: @"nullAI.plist"];
[UNIVERSE addEntity: ship];
[ship setStatus: STATUS_COCKPIT_DISPLAY];
[ship release];
}

View File

@ -2054,9 +2054,9 @@ static int scriptRandomSeed = -1; // ensure proper random function
[ship setScanClass:CLASS_NO_DRAW];
[ship setRoll:M_PI/5.0];
[ship setPitch:M_PI/10.0];
[[ship getAI] setStateMachine:@"nullAI.plist"];
[ship switchAITo:@"nullAI.plist"];
[ship setPendingEscortCount:0];
[UNIVERSE addEntity:ship];
[UNIVERSE addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
[ship setStatus:STATUS_COCKPIT_DISPLAY];
[ship release];
@ -2183,7 +2183,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
{
AI* se1AI = [se1 getAI];
[se1 setFuel:MAX(PLAYER_MAX_FUEL, [se1 fuelCapacity])];
[se1AI setStateMachine:@"exitingTraderAI.plist"];
[se1AI setStateMachine:@"exitingTraderAI.plist"]; // lets them return to their previous state after the jump
[se1AI setState:@"EXIT_SYSTEM"];
// The following should prevent all ships leaving at once (freezes oolite on slower machines)
[se1AI setNextThinkTime:[UNIVERSE getTime] + 3 + (ranrot_rand() & 15)];
@ -2534,10 +2534,10 @@ static int scriptRandomSeed = -1; // ensure proper random function
OOLog(kOOLogDebugProcessSceneStringAddModel, @"::::: adding model to scene:'%@'", ship);
[ship setOrientation: model_q];
[ship setPosition: model_p0];
[ship setStatus: STATUS_COCKPIT_DISPLAY];
[ship setScanClass: CLASS_NO_DRAW];
[UNIVERSE addEntity: ship];
[[ship getAI] setStateMachine: @"nullAI.plist"];
[ship switchAITo: @"nullAI.plist"];
[UNIVERSE addEntity: ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
[ship setStatus: STATUS_COCKPIT_DISPLAY];
[ship setRoll: 0.0];
[ship setPitch: 0.0];
[ship setVelocity: kZeroVector];
@ -2568,10 +2568,10 @@ static int scriptRandomSeed = -1; // ensure proper random function
OOLog(kOOLogDebugProcessSceneStringAddModel, @"::::: adding model to scene:'%@'", doppelganger);
[doppelganger setOrientation: model_q];
[doppelganger setPosition: model_p0];
[doppelganger setStatus: STATUS_COCKPIT_DISPLAY];
[doppelganger setScanClass: CLASS_NO_DRAW];
[doppelganger switchAITo: @"nullAI.plist"];
[UNIVERSE addEntity: doppelganger];
[[doppelganger getAI] setStateMachine: @"nullAI.plist"];
[doppelganger setStatus: STATUS_COCKPIT_DISPLAY];
[doppelganger setRoll: 0.0];
[doppelganger setPitch: 0.0];
[doppelganger setVelocity: kZeroVector];
@ -2666,11 +2666,10 @@ static int scriptRandomSeed = -1; // ensure proper random function
[billboard setPosition:vector_add([billboard position], model_p0)];
[billboard setStatus: STATUS_COCKPIT_DISPLAY];
OOLog(kOOLogDebugProcessSceneStringAddBillboard, @"::::: adding billboard:'%@' to scene.", billboard);
[UNIVERSE addEntity: billboard];
[billboard setStatus: STATUS_COCKPIT_DISPLAY];
[billboard release];
return YES;

View File

@ -147,7 +147,7 @@ MA 02110-1301, USA.
ShipEntity* container = [UNIVERSE newShipWithRole:@"cargopod"];
if (container)
{
// Shouldn't there be a [UNIVERSE addEntity:] here? -- Ahruman
// the cargopod ship is just being set up. If ejected, will call UNIVERSE addEntity
[container wasAddedToUniverse];
[container setScanClass: CLASS_CARGO];
[container setCommodity:type andAmount:smaller_quantity];
@ -169,7 +169,7 @@ MA 02110-1301, USA.
ShipEntity* container = [UNIVERSE newShipWithRole:@"cargopod"];
if (container)
{
// Shouldn't there be a [UNIVERSE addEntity:] here? -- Ahruman
// the cargopod ship is just being set up. If ejected, will call UNIVERSE addEntity
[container wasAddedToUniverse];
[container setScanClass: CLASS_CARGO];
[container setStatus:STATUS_IN_HOLD];

View File

@ -771,6 +771,7 @@ BOOL class_masslocks(int some_class);
- (void) enterWormhole:(WormholeEntity *) w_hole replacing:(BOOL)replacing;
- (void) enterWitchspace;
- (void) leaveWitchspace;
- (void) witchspaceLeavingEffects;
- (void) markAsOffender:(int)offence_value;

View File

@ -117,6 +117,7 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
- (void) addSubEntity:(Entity *) subent;
- (void) addSubentityToCollisionRadius:(Entity*) subent;
- (ShipEntity *) launchPodWithCrew:(NSArray *)podCrew;
// equipment
- (NSDictionary *) eqDictionaryWithType:(OOEquipmentType *) type isDamaged:(BOOL) isDamaged;
@ -1069,13 +1070,12 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
ex_pos.z += dd * 6.0 * (randf() - 0.5);
[escorter setPosition:ex_pos];
[escorter setStatus:STATUS_IN_FLIGHT];
//[escorter setStatus:STATUS_IN_FLIGHT];
[escorter setPrimaryRole:defaultRole]; //for mothership
[escorter setScanClass:scanClass]; // you are the same as I
if ([self bounty] == 0) [escorter setBounty:0]; // Avoid dirty escorts for clean mothers
[UNIVERSE addEntity:escorter];
// find the right outoAI.
escortShipDict = [escorter shipInfoDictionary];
autoAIMap = [ResourceManager dictionaryFromFilesNamed:@"autoAImap.plist" inFolder:@"Config" andMerge:YES];
autoAI = [autoAIMap oo_stringForKey:defaultRole];
@ -1083,16 +1083,17 @@ static NSString * const kOOLogEntityBehaviourChanged = @"entity.behaviour.change
{
autoAI = [autoAIMap oo_stringForKey:@"escort" defaultValue:@"nullAI.plist"];
}
if ((escortShipKey || escortRole) && [escortShipDict oo_fuzzyBooleanForKey:@"auto_ai" defaultValue:YES]) //setAITo only once!
escortAI = [escorter getAI];
// Let the populator decide which AI to use, unless we have a working alternative AI & we specify auto_ai = NO !
if ( ((escortShipKey || escortRole) && [escortShipDict oo_fuzzyBooleanForKey:@"auto_ai" defaultValue:YES])
|| ([[escortAI name] isEqualToString: @"nullAI.plist"] && ![autoAI isEqualToString:@"nullAI.plist"]) )
{
[escorter setAITo:autoAI];
[escorter switchAITo:autoAI];
}
escortAI = [escorter getAI];
if ([[escortAI name] isEqualToString: @"nullAI.plist"] && ![autoAI isEqualToString:@"nullAI.plist"])
{
[escortAI setStateMachine:autoAI]; // must happen after adding to the UNIVERSE!
}
[UNIVERSE addEntity:escorter]; // STATUS_IN_FLIGHT, AI state GLOBAL
[escorter setGroup:escortGroup];
[escorter setOwner:self]; // make self group leader
@ -1348,6 +1349,27 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
}
- (ShipEntity *) launchPodWithCrew:(NSArray *)podCrew
{
ShipEntity *pod = nil;
pod = [UNIVERSE newShipWithRole:[shipinfoDictionary oo_stringForKey:@"escape_pod_model" defaultValue:@"escape-capsule"]];
if (pod)
{
[pod setOwner:self];
//[pod setScanClass: CLASS_CARGO];
[pod setCommodity:[UNIVERSE commodityForName:@"Slaves"] andAmount:1];
[pod setCrew:podCrew];
[pod switchAITo:@"homeAI.plist"];
[self dumpItem:pod]; // includes UNIVERSE addEntity
//[[pod getAI] setState:@"GLOBAL"];
[pod release]; //release
}
return pod;
}
- (BOOL) validForAddToUniverse
{
if (shipinfoDictionary == nil)
@ -4609,6 +4631,7 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
- (void) setStatus:(OOEntityStatus) stat
{
if ([self status] == stat) return;
[super setStatus:stat];
if (stat == STATUS_LAUNCHING)
{
@ -5291,9 +5314,9 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
[container setVelocity:v];
quaternion_set_random(&q);
[container setOrientation:q];
[container setStatus:STATUS_IN_FLIGHT];
//[container setStatus:STATUS_IN_FLIGHT];
[container setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:container];
[UNIVERSE addEntity:container]; // STATUS_IN_FLIGHT, AI state GLOBAL
containerAI = [container getAI];
if ([containerAI hasSuspendedStateMachines]) // check if new or recycled cargo.
{
@ -5301,10 +5324,6 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
[container setThrust:[container maxThrust]]; // restore old value. Was set to zero on previous scooping.
[container setOwner:container];
}
else
{
[containerAI setState:@"GLOBAL"];
}
}
}
}
@ -5334,10 +5353,10 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
[rock setVelocity:v];
quaternion_set_random(&q);
[rock setOrientation:q];
[rock setStatus:STATUS_IN_FLIGHT];
//[rock setStatus:STATUS_IN_FLIGHT];
[rock setScanClass: CLASS_ROCK];
[UNIVERSE addEntity:rock];
[[rock getAI] setState:@"GLOBAL"];
[UNIVERSE addEntity:rock]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[rock getAI] setState:@"GLOBAL"];
[rock release];
}
}
@ -5372,10 +5391,10 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
[rock setVelocity:v];
quaternion_set_random(&q);
[rock setOrientation:q];
[rock setStatus:STATUS_IN_FLIGHT];
//[rock setStatus:STATUS_IN_FLIGHT];
[rock setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:rock];
[[rock getAI] setState:@"GLOBAL"];
[UNIVERSE addEntity:rock]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[rock getAI] setState:@"GLOBAL"];
[rock release];
}
}
@ -5426,8 +5445,8 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
[wreck setHeatInsulation: 1.0e7]; // very large! so it won't cool down
[wreck setEnergy: 750.0 * randf() + 250.0 * i + 100.0]; // burn for 0.25s -> 1.25s
[wreck setStatus:STATUS_IN_FLIGHT];
[UNIVERSE addEntity:wreck];
//[wreck setStatus:STATUS_IN_FLIGHT];
[UNIVERSE addEntity:wreck]; // STATUS_IN_FLIGHT, AI state GLOBAL
[wreck performTumble];
[wreck rescaleBy: 1.0/scale_factor];
[wreck release];
@ -5458,10 +5477,10 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
[plate setOrientation:q];
[plate setScanClass: CLASS_CARGO];
[plate setCommodity:[UNIVERSE commodityForName:@"Alloys"] andAmount:1];
[UNIVERSE addEntity:plate];
[plate setStatus:STATUS_IN_FLIGHT];
[UNIVERSE addEntity:plate]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[plate setStatus:STATUS_IN_FLIGHT];
[plate setTemperature:[self temperature] * EJECTA_TEMP_FACTOR];
[[plate getAI] setState:@"GLOBAL"];
//[[plate getAI] setState:@"GLOBAL"];
[plate release];
}
}
@ -5717,9 +5736,9 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
rpos.z += (ranrot_rand() % 7) - 3;
[container setPosition:rpos];
[container setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:container];
[[container getAI] setState:@"GLOBAL"];
[container setStatus:STATUS_IN_FLIGHT];
[UNIVERSE addEntity:container]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[container getAI] setState:@"GLOBAL"];
//[container setStatus:STATUS_IN_FLIGHT];
[container release];
if (n_cargo > 0)
n_cargo--; // count down extra cargo
@ -7286,7 +7305,7 @@ BOOL class_masslocks(int some_class)
[missile setPosition:origin];
[missile addTarget:target];
[missile setOrientation:q1];
[missile setStatus:STATUS_IN_FLIGHT]; // necessary to get it going!
//[missile setStatus:STATUS_IN_FLIGHT]; // necessary to get it going!
[missile setIsMissileFlag:YES];
[missile setVelocity:vel];
[missile setSpeed:150.0f];
@ -7294,7 +7313,7 @@ BOOL class_masslocks(int some_class)
[missile resetShotTime];
missile_launch_time = [UNIVERSE getTime] + missile_load_time; // set minimum launchtime for the next missile.
[UNIVERSE addEntity:missile];
[UNIVERSE addEntity:missile]; // STATUS_IN_FLIGHT, AI state GLOBAL
[missile release]; //release
// missile lives on after UNIVERSE addEntity
@ -7386,12 +7405,12 @@ BOOL class_masslocks(int some_class)
[bomb setPitch:random_pitch];
[bomb setVelocity:vel];
[bomb setScanClass:CLASS_MINE]; // TODO should be CLASS_ENERGY_BOMB
[bomb setStatus:STATUS_IN_FLIGHT];
//[bomb setStatus:STATUS_IN_FLIGHT];
[bomb setEnergy:5.0]; // 5 second countdown
[bomb setBehaviour:BEHAVIOUR_ENERGY_BOMB_COUNTDOWN];
[bomb setOwner:self];
[UNIVERSE addEntity:bomb];
[[bomb getAI] setState:@"GLOBAL"];
[UNIVERSE addEntity:bomb]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[bomb getAI] setState:@"GLOBAL"];
[bomb release];
if (self != [PlayerEntity sharedPlayer]) // get the heck out of here
@ -7408,7 +7427,7 @@ BOOL class_masslocks(int some_class)
{
OOUniversalID result = NO_TARGET;
ShipEntity *mainPod = nil, *pod = nil;
unsigned n_pods;
unsigned n_pods, i;
/* BUG: player can't launch escape pod in interstellar space (because
there is no standard place for ressurection), but NPCs can.
@ -7420,53 +7439,31 @@ BOOL class_masslocks(int some_class)
// check number of pods aboard -- require at least one.
n_pods = [shipinfoDictionary oo_unsignedIntForKey:@"has_escape_pod"];
pod = [UNIVERSE newShipWithRole:[shipinfoDictionary oo_stringForKey:@"escape_pod_model" defaultValue:@"escape-capsule"]];
mainPod = pod;
if (pod)
if (crew) // transfer crew
{
[pod setOwner:self];
[pod setScanClass: CLASS_CARGO];
[pod setCommodity:[UNIVERSE commodityForName:@"Slaves"] andAmount:1];
if (crew) // transfer crew
// make sure crew inherit any legalStatus
for (i = 0; i < [crew count]; i++)
{
// make sure crew inherit any legalStatus
unsigned i;
for (i = 0; i < [crew count]; i++)
{
OOCharacter *ch = (OOCharacter*)[crew objectAtIndex:i];
[ch setLegalStatus: [self legalStatus] | [ch legalStatus]];
}
[pod setCrew:crew];
OOCharacter *ch = (OOCharacter*)[crew objectAtIndex:i];
[ch setLegalStatus: [self legalStatus] | [ch legalStatus]];
}
mainPod = [self launchPodWithCrew:crew];
if (mainPod)
{
result = [mainPod universalID];
[self setCrew:nil];
[self setHulk:YES]; //CmdrJames experiment with fixing ejection behaviour
}
[[pod getAI] setStateMachine:@"homeAI.plist"];
[self dumpItem:pod];
[[pod getAI] setState:@"GLOBAL"];
[pod release]; //release
result = [pod universalID];
}
// launch other pods (passengers)
unsigned i;
for (i = 1; i < n_pods; i++)
{
pod = [UNIVERSE newShipWithRole:@"escape-capsule"];
if (pod)
{
Random_Seed orig = [UNIVERSE systemSeedForSystemNumber:gen_rnd_number()];
[pod setOwner:self];
[pod setScanClass: CLASS_CARGO];
[pod setCommodity:[UNIVERSE commodityForName:@"Slaves"] andAmount:1];
[pod setCrew:[NSArray arrayWithObject:[OOCharacter randomCharacterWithRole:@"passenger" andOriginalSystem:orig]]];
[[pod getAI] setStateMachine:@"homeAI.plist"];
[self dumpItem:pod];
[[pod getAI] setState:@"GLOBAL"];
[pod release]; //release
}
}
[self doScriptEvent:@"shipLaunchedEscapePod" withArgument:mainPod];
// launch other pods (passengers)
for (i = 1; i < n_pods; i++)
{
Random_Seed orig = [UNIVERSE systemSeedForSystemNumber:gen_rnd_number()];
[self launchPodWithCrew:[NSArray arrayWithObject:[OOCharacter randomCharacterWithRole:@"passenger" andOriginalSystem:orig]]];
}
if (mainPod) [self doScriptEvent:@"shipLaunchedEscapePod" withArgument:mainPod];
return result;
}
@ -7561,9 +7558,9 @@ BOOL class_masslocks(int some_class)
[jetto setPitch:random_pitch];
[jetto setVelocity:vel];
[jetto setScanClass: CLASS_CARGO];
[jetto setStatus: STATUS_IN_FLIGHT];
//[jetto setStatus: STATUS_IN_FLIGHT];
[jetto setTemperature:[self temperature] * EJECTA_TEMP_FACTOR];
[UNIVERSE addEntity:jetto];
[UNIVERSE addEntity:jetto]; // STATUS_IN_FLIGHT, AI state GLOBAL
jettoAI = [jetto getAI];
if ([jettoAI hasSuspendedStateMachines]) // check if this was previos scooped cargo.
@ -7572,10 +7569,7 @@ BOOL class_masslocks(int some_class)
[jetto setOwner:jetto];
[jettoAI exitStateMachineWithMessage:nil]; // exit nullAI.
}
else
{
[jettoAI setState:@"GLOBAL"];
}
cargo_dump_time = [UNIVERSE getTime];
return result;
}
@ -8165,14 +8159,14 @@ BOOL class_masslocks(int some_class)
{
[self removeEquipmentItem:@"EQ_ESCAPE_POD"];
[shipAI setStateMachine:@"nullAI.plist"];
[shipAI setState:@"GLOBAL"];
//[shipAI setState:@"GLOBAL"]; // alreaday set inside setStateMachine
behaviour = BEHAVIOUR_IDLE;
frustration = 0.0;
[self setScanClass: CLASS_CARGO]; // we're unmanned now!
thrust = thrust * 0.5;
desired_speed = 0.0;
//maxFlightSpeed = 0.0;
[self setHulk:YES];
//[self setHulk:YES]; // already set inside launcEscapeCapsule
if ([self hasEscorts])
{
@ -8289,8 +8283,8 @@ BOOL class_masslocks(int some_class)
[self setStatus:STATUS_LAUNCHING];
[self doScriptEvent:@"shipWillLaunchFromStation" withArgument:station];
[UNIVERSE addEntity:self]; // STATUS_IN_FLIGHT, AI state GLOBAL
[shipAI message:@"LAUNCHED"];
[UNIVERSE addEntity:self];
}
@ -8337,31 +8331,36 @@ BOOL class_masslocks(int some_class)
int w_space_seed = 1234567;
- (void) leaveWitchspace
{
Vector pos = [UNIVERSE getWitchspaceExitPosition];
Quaternion q_rtn = [UNIVERSE getWitchspaceExitRotation];
Quaternion q1 = [UNIVERSE getWitchspaceExitRotation];
double d1 = SCANNER_MAX_RANGE * (randf() - randf());
// try to ensure healthy random numbers
//
ranrot_srand(w_space_seed);
w_space_seed = ranrot_rand();
position = pos;
double d1 = SCANNER_MAX_RANGE * (randf() - randf());
if (abs(d1) < 500.0) // no closer than 500m
d1 += ((d1 > 0.0)? 500.0: -500.0);
Quaternion q1 = q_rtn;
quaternion_set_random(&q1);
Vector v1 = vector_forward_from_quaternion(q1);
position = [UNIVERSE getWitchspaceExitPosition];
position.x += v1.x * d1; // randomise exit position
position.y += v1.y * d1;
position.z += v1.z * d1;
orientation = q_rtn;
[self witchspaceLeavingEffects];
}
- (void) witchspaceLeavingEffects
{
// all ships exiting witchspace will share the same orientation.
orientation = [UNIVERSE getWitchspaceExitRotation];
flightRoll = 0.0;
flightPitch = 0.0;
flightSpeed = maxFlightSpeed * 0.25;
[UNIVERSE addEntity:self]; // AI and status get initialised here
[self setStatus:STATUS_LAUNCHING];
[shipAI message:@"EXITED_WITCHSPACE"];
[UNIVERSE addEntity:self];
// witchspace exit effects here
ParticleEntity *ring1 = [[ParticleEntity alloc] initHyperringFromShip:self]; // retained
@ -8569,7 +8568,7 @@ int w_space_seed = 1234567;
deployCount = ranrot_rand() % escortCount + 1;
// Deply deployCount idle escorts.
// Deploy deployCount idle escorts.
target = [self primaryTarget];
for (escortEnum = [idleEscorts objectEnumerator]; (escort = [escortEnum nextObject]); )
{

View File

@ -1493,13 +1493,13 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
[ship setCargoFlag:CARGO_FLAG_FULL_PLENTIFUL];
if (sunskimmer)
{
[[ship getAI] setStateMachine:@"route2sunskimAI.plist"];
[ship switchAITo:@"route2sunskimAI.plist"];
if([ship heatInsulation] < 7) [ship setHeatInsulation:7];
// even with this value the slow sunskim-anaconda will burn in a big sun.
}
else
{
[[ship getAI] setStateMachine:@"exitingTraderAI.plist"];
[ship switchAITo:@"exitingTraderAI.plist"];
if([ship fuel] == 0) [ship setFuel:70];
}
}
@ -1567,7 +1567,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
[escort_ship setGroup:escortGroup];
[escort_ship setOwner:ship];
[[escort_ship getAI] setStateMachine:@"escortAI.plist"];
[escort_ship switchAITo:@"escortAI.plist"];
[self addShipToLaunchQueue:escort_ship];
[escort_ship release];
@ -1642,7 +1642,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
[police_ship addTarget:[UNIVERSE entityForUniversalID:police_target]];
[police_ship setScanClass:CLASS_POLICE];
[police_ship setBounty:0];
[[police_ship getAI] setStateMachine:@"policeInterceptAI.plist"];
[police_ship switchAITo:@"policeInterceptAI.plist"];
[self addShipToLaunchQueue:police_ship];
[police_ship autorelease];
defenders_launched++;
@ -1703,7 +1703,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
if ([defense_ship isPolice] || [defense_ship hasPrimaryRole:@"hermit-ship"])
{
[defense_ship setStateMachine:defense_ship_ai];
[defense_ship switchAITo:defense_ship_ai];
}
[defense_ship setPrimaryRole:@"defense_ship"];
@ -1759,7 +1759,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
[scavenger_ship setScanClass: CLASS_NEUTRAL];
[scavenger_ship setGroup:[self stationGroup]]; // who's your Daddy -- FIXME: should we have a separate group for non-escort auxiliaires?
[[scavenger_ship getAI] setStateMachine:@"scavengerAI.plist"];
[scavenger_ship switchAITo:@"scavengerAI.plist"];
[self addShipToLaunchQueue:scavenger_ship];
[scavenger_ship autorelease];
}
@ -1791,7 +1791,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
scavengers_launched++;
[miner_ship setScanClass:CLASS_NEUTRAL];
[miner_ship setGroup:[self stationGroup]]; // who's your Daddy -- FIXME: should we have a separate group for non-escort auxiliaires?
[[miner_ship getAI] setStateMachine:@"minerAI.plist"];
[miner_ship switchAITo:@"minerAI.plist"];
[self addShipToLaunchQueue:miner_ship];
[miner_ship autorelease];
}
@ -1863,7 +1863,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
[shuttle_ship setScanClass: CLASS_NEUTRAL];
[shuttle_ship setCargoFlag:CARGO_FLAG_FULL_SCARCE];
[[shuttle_ship getAI] setStateMachine:@"fallingShuttleAI.plist"];
[shuttle_ship switchAITo:@"fallingShuttleAI.plist"];
[self addShipToLaunchQueue:shuttle_ship];
[shuttle_ship autorelease];
@ -1888,7 +1888,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
[escort_ship setScanClass: CLASS_NEUTRAL];
[escort_ship setCargoFlag: CARGO_FLAG_FULL_PLENTIFUL];
[[escort_ship getAI] setStateMachine:@"escortAI.plist"];
[escort_ship switchAITo:@"escortAI.plist"];
[self addShipToLaunchQueue:escort_ship];
[escort_ship release];
@ -1926,7 +1926,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
[patrol_ship setPrimaryRole:@"police"];
[patrol_ship setBounty:0];
[patrol_ship setGroup:[self stationGroup]]; // who's your Daddy
[[patrol_ship getAI] setStateMachine:@"planetPatrolAI.plist"];
[patrol_ship switchAITo:@"planetPatrolAI.plist"];
[self addShipToLaunchQueue:patrol_ship];
[self acceptPatrolReportFrom:patrol_ship];
[patrol_ship autorelease];

View File

@ -39,10 +39,6 @@
#import "OOEntityFilterPredicate.h"
// system.addShips not yet implemented
#define ADD_SHIPS 0
static JSObject *sSystemPrototype;
@ -52,7 +48,6 @@ static NSArray *FindJSVisibleEntities(EntityFilterPredicate predicate, void *par
static NSArray *FindShips(EntityFilterPredicate predicate, void *parameter, Entity *relativeTo, double range);
static NSComparisonResult CompareEntitiesByDistance(id a, id b, void *relativeTo);
static JSBool SystemGetProperty(JSContext *context, JSObject *this, jsval name, jsval *outValue);
static JSBool SystemSetProperty(JSContext *context, JSObject *this, jsval name, jsval *value);
@ -67,9 +62,10 @@ static JSBool SystemShipsWithRole(JSContext *context, JSObject *this, uintN argc
static JSBool SystemEntitiesWithScanClass(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemFilteredEntities(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
#if ADD_SHIPS
static JSBool SystemAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
#endif
static JSBool SystemAddGroup(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemAddShipsToRoute(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemAddGroupToRoute(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacyAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
static JSBool SystemLegacyAddSystemShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult);
@ -168,9 +164,10 @@ static JSFunctionSpec sSystemMethods[] =
{ "entitiesWithScanClass", SystemEntitiesWithScanClass, 1 },
{ "filteredEntities", SystemFilteredEntities, 2 },
#if ADD_SHIPS
{ "addShips", SystemAddShips, 3 },
#endif
{ "addGroup", SystemAddGroup, 3 },
{ "addShipsToRoute", SystemAddShipsToRoute, 2 },
{ "addGroupToRoute", SystemAddGroupToRoute, 2 },
{ "legacy_addShips", SystemLegacyAddShips, 2 },
{ "legacy_addSystemShips", SystemLegacyAddSystemShips, 3 },
@ -186,7 +183,7 @@ static JSFunctionSpec sSystemStaticMethods[] =
{
{ "systemNameForID", SystemStaticSystemNameForID, 1 },
{ "systemIDForName", SystemStaticSystemIDForName, 1 },
{ "infoForSystem", SystemStaticInfoForSystem, 2 },
{ "infoForSystem", SystemStaticInfoForSystem, 2 },
{ 0 }
};
@ -687,45 +684,152 @@ static JSBool SystemFilteredEntities(JSContext *context, JSObject *this, uintN a
}
#define DEFAULT_RADIUS 500.0
#if ADD_SHIPS
// Forum thread: http://www.aegidian.org/bb/viewtopic.php?t=3371
// addShips(role : String, count : Number, position: Vector[, radius: Number])
static JSBool SystemAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
NSString *role = nil;
int32 count;
int32 count = 0;
uintN consumed = 0;
Vector where;
double radius = DEFAULT_RADIUS;
uintN consumed;
double radius = NSNotFound; // a negative value means
id result = nil;
BOOL isGroup = [@"group" isEqualTo:JSValToNSString(context,*outResult)];
NSString *func = isGroup ? @"addGroup" : @"addShips";
*outResult = JSVAL_NULL;
role = JSValToNSString(context, argv[0]);
if (scString == nil)
if (role == nil)
{
OOReportJSError(context, @"System.%@(): role not defined.", @"addShips");
OOReportJSError(context, @"System.%@(): role not defined.", func);
return NO;
}
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJSError(context, @"System.%@(): expected positive count, got %@.", @"addShips", [NSString stringWithJavaScriptValue:argv[1] inContext:context]);
OOReportJSError(context, @"System.%@(): expected %@, got '%@'.", func, @"positive count", [NSString stringWithJavaScriptValue:argv[1] inContext:context]);
return NO;
}
if (!VectorFromArgumentList(context, @"System", @"addShips", argc - 2, argv + 2, &where, &consumed)) return YES;
argc += 2 + consumed;
argv += 2 + consumed;
if (argc != 0 && JS_ValueToNumber(context, argv[0], &radius))
if (!VectorFromArgumentListNoError(context, argc - 2, argv + 2, &where, &consumed))
{
OOReportJSError(context, @"System.%@(): expected %@, got '%@'.", func, @"position", [NSString stringWithJavaScriptValue:argv[2] inContext:context]);
return NO;
}
// Note: need a way to specify the use of witchspace-in effects (as in legacy_addShips).
OOReportJSError(context, @"System.addShips(): not implemented.");
if (argc > 2 + consumed)
{
if (!JSVAL_IS_NUMBER(argv[2 + consumed]))
{
OOReportJSError(context, @"System.%@(): expected %@, got '%@'.", func, @"radius", [NSString stringWithJavaScriptValue:argv[2 + consumed] inContext:context]);
return NO;
}
JS_ValueToNumber(context, argv[2 + consumed], &radius);
}
// Note: the use of witchspace-in effects (as in legacy_addShips). depends on proximity to the witchpoint.
//[UNIVERSE addShips:count withRole:role atPosition:where withCoordinateSystem:@"abs"];
result = [UNIVERSE addShipsAt:where withRole:role quantity:count withinRadius:radius asGroup:isGroup];
if (isGroup && result != nil)
{
if ([(NSArray *)result count] > 0) result = [(ShipEntity *)[(NSArray *)result objectAtIndex:0] group];
else result = nil;
}
*outResult = [result javaScriptValueInContext:context];
return YES;
}
#endif
// addGroup(role : String, count : Number, position: Vector)
static JSBool SystemAddGroup(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
jsval result = [@"group" javaScriptValueInContext:context];
SystemAddShips(context, this, argc, argv, &result);
*outResult = result;
return YES;
}
// addShipsToRoute(role : String, count : Number,[ , position: Number] [, route: String])
static JSBool SystemAddShipsToRoute(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
NSString *role = nil;
NSString *route = @"wp";
NSString *routes = @" wp pw ws sw sp ps";
int32 count = 0;
double where = NSNotFound; // a negative value means random positioning!
id result = nil;
BOOL isGroup = [@"group" isEqualTo:JSValToNSString(context,*outResult)];
NSString *func = isGroup ? @"addGroup" : @"addShips";
*outResult = JSVAL_NULL;
role = JSValToNSString(context, argv[0]);
if (role == nil)
{
OOReportJSError(context, @"System.%@(): role not defined.", func);
return NO;
}
if (!JS_ValueToInt32(context, argv[1], &count) || count < 1 || 64 < count)
{
OOReportJSError(context, @"System.%@(): expected %@, got '%@'.", func, @"positive count", [NSString stringWithJavaScriptValue:argv[1] inContext:context]);
return NO;
}
if (argc > 2 && !JSVAL_IS_NULL(argv[2]))
{
JS_ValueToNumber(context, argv[2], &where);
if (!JSVAL_IS_NUMBER(argv[2]) || where < 0.0f || where > 1.0f)
{
OOReportJSError(context, @"System.%@(): expected %@, got '%@'.", func, @"position along route", [NSString stringWithJavaScriptValue:argv[2] inContext:context]);
return NO;
}
}
if (argc > 3 && !JSVAL_IS_NULL(argv[3]))
{
route = JSValToNSString(context, argv[3]);
if (!JSVAL_IS_STRING(argv[3]) || route == nil || [routes rangeOfString:[NSString stringWithFormat:@" %@",route] options:NSCaseInsensitiveSearch].length !=3)
{
OOReportJSError(context, @"System.%@(): expected %@, got '%@'.", func, @"route string", [NSString stringWithJavaScriptValue:argv[3] inContext:context]);
return NO;
}
route = [route lowercaseString];
}
// Note: the use of witchspace-in effects (as in legacy_addShips). depends on proximity to the witchpoint.
result = [UNIVERSE addShipsToRoute:route withRole:role quantity:count routeFraction:where asGroup:isGroup];
if (isGroup && result != nil)
{
if ([(NSArray *)result count] > 0) result = [(ShipEntity *)[(NSArray *)result objectAtIndex:0] group];
else result = nil;
}
*outResult = [result javaScriptValueInContext:context];
return YES;
}
// addGroupToRoute(role : String, count : Number, position: Number[, route: String])
static JSBool SystemAddGroupToRoute(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)
{
jsval result = [@"group" javaScriptValueInContext:context];
SystemAddShipsToRoute(context, this, argc, argv, &result);
*outResult = result;
return YES;
}
// legacy_addShips(role : String, count : Number)
static JSBool SystemLegacyAddShips(JSContext *context, JSObject *this, uintN argc, jsval *argv, jsval *outResult)

View File

@ -318,6 +318,10 @@ enum
- (void) witchspaceShipWithPrimaryRole:(NSString *)role;
- (ShipEntity *) spawnShipWithRole:(NSString *) desc near:(Entity *) entity;
- (ShipEntity *) addShipAt:(Vector)pos withRole:(NSString *)role withinRadius:(GLfloat)radius;
- (NSArray *) addShipsAt:(Vector)pos withRole:(NSString *)role quantity:(unsigned)count withinRadius:(GLfloat)radius asGroup:(BOOL)isGroup;
- (NSArray *) addShipsToRoute:(NSString *)route withRole:(NSString *)role quantity:(unsigned)count routeFraction:(double)routeFraction asGroup:(BOOL)isGroup;
- (BOOL) roleIsPirateVictim:(NSString *)role;
- (void) set_up_break_pattern:(Vector) pos quaternion:(Quaternion) q forDocking:(BOOL) forDocking;

View File

@ -170,6 +170,7 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context);
- (void) initSettings;
- (void) initPlayerSettings;
- (ShipEntity *) spawnPatrolShipAt:(Vector)launchPos alongRoute:(Vector)v_route withOffset:(double)ship_location;
- (Vector) fractionalPositionFrom:(Vector)point0 to:(Vector)point1 withFraction:(double)routeFraction;
- (void) resetSystemDataCache;
@ -733,10 +734,10 @@ OOINLINE size_t class_getInstanceSize(Class cls)
[thargoid setOrientation:tharg_quaternion];
[thargoid setScanClass: CLASS_THARGOID];
[thargoid setBounty:100];
[thargoid setStatus:STATUS_IN_FLIGHT];
//[thargoid setStatus:STATUS_IN_FLIGHT];
[thargoid setGroup:thargoidGroup];
[self addEntity:thargoid];
[self addEntity:thargoid]; // STATUS_IN_FLIGHT, AI state GLOBAL
[thargoid release];
}
@ -1010,14 +1011,14 @@ OOINLINE size_t class_getInstanceSize(Class cls)
if (a_station != nil)
{
[a_station setStatus:STATUS_ACTIVE];
//[a_station setStatus:STATUS_ACTIVE];
[a_station setOrientation: q_station];
[a_station setPosition: stationPos];
[a_station setPitch: 0.0];
[a_station setScanClass: CLASS_STATION];
[a_station setPlanet:[self planet]];
[a_station setEquivalentTechLevel:techlevel];
[self addEntity:a_station];
[self addEntity:a_station]; // STATUS_ACTIVE, AI state GLOBAL
}
cachedSun = a_sun;
@ -1040,24 +1041,23 @@ OOINLINE size_t class_getInstanceSize(Class cls)
[nav_buoy setPitch: 0.15];
[nav_buoy setPosition:[a_station getBeaconPosition]];
[nav_buoy setScanClass: CLASS_BUOY];
[self addEntity:nav_buoy];
[nav_buoy setStatus:STATUS_IN_FLIGHT];
[self addEntity:nav_buoy]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[nav_buoy setStatus:STATUS_IN_FLIGHT];
[nav_buoy release];
}
}
/*--*/
/*- nav beacon witchpoint -*/
Vector witchpoint = [self getWitchspaceExitPosition]; // witchpoint
nav_buoy = [self newShipWithRole:@"buoy-witchpoint"]; // retain count = 1
if (nav_buoy)
{
[nav_buoy setRoll: 0.10];
[nav_buoy setPitch: 0.15];
[nav_buoy setPosition:witchpoint];
[nav_buoy setPosition:[self getWitchspaceExitPosition]];
[nav_buoy setScanClass: CLASS_BUOY];
[self addEntity:nav_buoy];
[nav_buoy setStatus:STATUS_IN_FLIGHT];
[self addEntity:nav_buoy]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[nav_buoy setStatus:STATUS_IN_FLIGHT];
[nav_buoy release];
}
/*--*/
@ -1358,7 +1358,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[trader_ship setPosition:launchPos];
[trader_ship setBounty:0];
[trader_ship setCargoFlag:CARGO_FLAG_FULL_SCARCE];
[trader_ship setStatus:STATUS_IN_FLIGHT];
//[trader_ship setStatus:STATUS_IN_FLIGHT];
if (([trader_ship pendingEscortCount] > 0)&&((Ranrot() % 7) < government)) // remove escorts if we feel safe
{
@ -1366,9 +1366,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[trader_ship setPendingEscortCount:(nx > 0) ? nx : 0];
}
[self addEntity:trader_ship];
[self addEntity:trader_ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
// [[trader_ship getAI] setStateMachine:@"route1traderAI.plist"]; // must happen after adding to the universe!
[[trader_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
//[[trader_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
[trader_ship release];
}
@ -1419,15 +1419,15 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[pirate_ship setScanClass: CLASS_NEUTRAL];
}
[pirate_ship setPosition:launchPos];
[pirate_ship setStatus:STATUS_IN_FLIGHT];
//[pirate_ship setStatus:STATUS_IN_FLIGHT];
[pirate_ship setBounty: 20 + government + wolfPackCounter + (Ranrot() & 7)];
[pirate_ship setCargoFlag: CARGO_FLAG_PIRATE];
[pirate_ship setGroup:wolfpackGroup];
[self addEntity:pirate_ship];
[self addEntity:pirate_ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
// [[pirate_ship getAI] setStateMachine:@"pirateAI.plist"]; // must happen after adding to the universe!
[[pirate_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
//[[pirate_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
[pirate_ship release];
}
@ -1456,7 +1456,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
}
// [hunter_ship setAITo:@"route1patrolAI.plist"]; // standard AI, no need to set it again.
[[hunter_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
//[[hunter_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
}
[pool release];
@ -1480,9 +1480,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[thargoid_ship setScanClass: CLASS_THARGOID];
[thargoid_ship setPosition:launchPos];
[thargoid_ship setBounty:100];
[thargoid_ship setStatus:STATUS_IN_FLIGHT];
[self addEntity:thargoid_ship];
[[thargoid_ship getAI] setState:@"GLOBAL"];
//[thargoid_ship setStatus:STATUS_IN_FLIGHT];
[self addEntity:thargoid_ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[thargoid_ship getAI] setState:@"GLOBAL"];
[thargoid_ship release];
}
@ -1552,7 +1552,7 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[trader_ship setBounty:0];
[trader_ship setCargoFlag:CARGO_FLAG_FULL_PLENTIFUL];
if([trader_ship heatInsulation] < 7) [trader_ship setHeatInsulation:7]; // With this value most ships will survive the sun trip.
[trader_ship setStatus:STATUS_IN_FLIGHT];
//[trader_ship setStatus:STATUS_IN_FLIGHT];
if (([trader_ship pendingEscortCount] > 0)&&((Ranrot() % 7) < government)) // remove escorts if we feel safe
{
@ -1560,9 +1560,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[trader_ship setPendingEscortCount:(nx > 0) ? nx : 0];
}
[self addEntity:trader_ship];
[self addEntity:trader_ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
// [[trader_ship getAI] setStateMachine:@"route2sunskimAI.plist"]; // must happen after adding to the universe!
[[trader_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
//[[trader_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
[trader_ship release];
}
@ -1611,15 +1611,15 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
if (pirate_ship->scanClass == CLASS_NOT_SET)
[pirate_ship setScanClass: CLASS_NEUTRAL];
[pirate_ship setPosition: launchPos];
[pirate_ship setStatus: STATUS_IN_FLIGHT];
//[pirate_ship setStatus: STATUS_IN_FLIGHT];
[pirate_ship setBounty: 20 + government + wolfPackCounter + (Ranrot() % 7)];
[pirate_ship setCargoFlag: CARGO_FLAG_PIRATE];
[pirate_ship setGroup:wolfpackGroup];
[self addEntity:pirate_ship];
[self addEntity:pirate_ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
// [[pirate_ship getAI] setStateMachine:@"pirateAI.plist"]; // must happen after adding to the universe!
[[pirate_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
//[[pirate_ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe to start the AI!
[pirate_ship release];
}
@ -1705,9 +1705,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[asteroid setScanClass: CLASS_ROCK];
[asteroid setPosition:launchPos];
[asteroid setVelocity:spawnVel];
[asteroid setStatus:STATUS_IN_FLIGHT];
[self addEntity:asteroid];
[[asteroid getAI] setState:@"GLOBAL"];
//[asteroid setStatus:STATUS_IN_FLIGHT];
[self addEntity:asteroid]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[asteroid getAI] setState:@"GLOBAL"]; // they're classed as ships internally so it's done inside addEntity.
[asteroid release];
rocks++;
}
@ -1731,9 +1731,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[hermit setScanClass: CLASS_ROCK];
[hermit setPosition:launchPos];
[hermit setVelocity:spawnVel];
[hermit setStatus:STATUS_IN_FLIGHT];
[self addEntity:hermit];
[[hermit getAI] setState:@"GLOBAL"];
//[hermit setStatus:STATUS_IN_FLIGHT];
[self addEntity:hermit]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[hermit getAI] setState:@"GLOBAL"]; //classed as ship
[hermit release];
#if DEAD_STORE
clusterSize++;
@ -1781,10 +1781,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
if (ship->scanClass == CLASS_NOT_SET)
[ship setScanClass: CLASS_NEUTRAL];
[ship setPosition:launchPos];
[self addEntity:ship];
[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
//[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[ship release];
}
@ -2079,9 +2078,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
if (ship->scanClass == CLASS_NOT_SET)
[ship setScanClass: CLASS_NEUTRAL];
[ship setPosition:launchPos];
[self addEntity:ship];
[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
//[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[ship release];
return YES;
@ -2171,9 +2170,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
quaternion_set_random(&qr);
[ship setOrientation:qr];
[self addEntity:ship];
[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
//[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[ship release];
ship_positions[i] = ship_pos;
@ -2286,9 +2285,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
if (ship->scanClass == CLASS_NOT_SET)
[ship setScanClass: CLASS_NEUTRAL];
[ship setPosition: pos];
[self addEntity:ship];
[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
//[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[ship release];
@ -2354,9 +2353,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
}
}
[self addEntity:ship];
[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
//[ship setStatus:STATUS_IN_FLIGHT]; // or ships that were 'demo' ships become invisible!
[ship release];
return YES;
@ -2389,9 +2388,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
{
[ship setCargoFlag: CARGO_FLAG_FULL_SCARCE];
if (randf() > 0.10)
[[ship getAI] setStateMachine:@"route1traderAI.plist"];
[ship switchAITo:@"route1traderAI.plist"];
else
[[ship getAI] setStateMachine:@"route2sunskimAI.plist"]; // route3 really, but the AI's the same
[ship switchAITo:@"route2sunskimAI.plist"]; // route3 really, but the AI's the same
if (([ship pendingEscortCount] > 0)&&((Ranrot() % 7) < government)) // remove escorts if we feel safe
{
@ -2409,9 +2408,9 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[OOCharacter randomCharacterWithRole:role
andOriginalSystem: systems[Ranrot() & 255]]]];
[ship leaveWitchspace]; // gets added to the universe here!
[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
[ship setStatus:STATUS_IN_FLIGHT]; // or ships may not werk rite d'uh!
[ship leaveWitchspace]; // calls UNIVERSE addEntity: STATUS_IN_FLIGHT, AI state GLOBAL
//[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
//[ship setStatus:STATUS_IN_FLIGHT]; // or ships may not werk rite d'uh!
[ship release];
}
@ -2454,16 +2453,174 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
}
[ship setPosition:spawn_pos];
[ship setOrientation:spawn_q];
[self addEntity:ship];
[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
[ship setStatus:STATUS_IN_FLIGHT];
[ship autorelease];
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
//[[ship getAI] setState:@"GLOBAL"]; // must happen after adding to the universe!
//[ship setStatus:STATUS_IN_FLIGHT];
[ship release];
}
return ship;
}
- (ShipEntity *) addShipAt:(Vector)pos withRole:(NSString *)role withinRadius:(GLfloat)radius
{
ShipEntity *ship = [self newShipWithRole:role]; // is retained
if (ship)
{
if (radius == NSNotFound)
{
GLfloat scalar = 1.0;
[self coordinatesForPosition:pos withCoordinateSystem:@"abs" returningScalar:&scalar];
// randomise
GLfloat rfactor = scalar;
if (rfactor > SCANNER_MAX_RANGE)
rfactor = SCANNER_MAX_RANGE;
if (rfactor < 1000)
rfactor = 1000;
pos.x += rfactor*(randf() - randf());
pos.y += rfactor*(randf() - randf());
pos.z += rfactor*(randf() - randf());
}
else // if (radius == 0.0f) changed from bounding box, seems to give acceptable results
{
Vector v_from_center = kZeroVector;
GLfloat walk_factor = 2.0f;
do
{
v_from_center.x += walk_factor * (randf() - 0.5);
v_from_center.y += walk_factor * (randf() - 0.5);
v_from_center.z += walk_factor * (randf() - 0.5); // drunkards walk
} while (vector_equal(v_from_center, kZeroVector));
v_from_center = vector_normal(v_from_center); // guaranteed non-zero
pos = make_vector( pos.x + radius * v_from_center.x,
pos.y + radius * v_from_center.y,
pos.z + radius * v_from_center.z );
}
if ([ship hasRole:@"cargopod"]) [self fillCargopodWithRandomCargo:ship];
if ([ship scanClass] == CLASS_NOT_SET) [ship setScanClass: CLASS_NEUTRAL];
if (![ship crew] && ![ship isUnpiloted] && !([ship scanClass] == CLASS_CARGO || [ship scanClass] == CLASS_ROCK))
[ship setCrew:[NSArray arrayWithObject:
[OOCharacter randomCharacterWithRole: role
andOriginalSystem: systems[Ranrot() & 255]]]];
[ship setPosition:pos];
Quaternion qr;
quaternion_set_random(&qr);
[ship setOrientation:qr];
if (distance([self getWitchspaceExitPosition], pos) > SCANNER_MAX_RANGE)
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL - ship is retained globally
else
[ship witchspaceLeavingEffects]; //includes addEntity: STATUS_IN_FLIGHT, AI state GLOBAL - ship is retained globally
[ship release];
}
return ship;
}
- (NSArray *) addShipsAt:(Vector)pos withRole:(NSString *)role quantity:(unsigned)count withinRadius:(GLfloat)radius asGroup:(BOOL)isGroup
{
NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count];
ShipEntity *ship = nil;
OOShipGroup *group = nil;
if (isGroup)
{
group = [OOShipGroup groupWithName:[NSString stringWithFormat:@"%@ group", role]];
}
while (count--)
{
ship = [self addShipAt:pos withRole:role withinRadius:radius];
if (ship != nil)
{
// TODO: avoid collisions!!!
if (isGroup) [ship setGroup:group];
[ships addObject:ship];
}
}
if ([ships count] == 0) return nil;
return [[ships copy] autorelease];
}
- (NSArray *) addShipsToRoute:(NSString *)route withRole:(NSString *)role quantity:(unsigned)count routeFraction:(double)routeFraction asGroup:(BOOL)isGroup
{
NSMutableArray *ships = [NSMutableArray arrayWithCapacity:count]; //return [[(NSArray *)theShips copy] autorelease];
ShipEntity *ship = nil;
Entity<OOStellarBody> *entity = nil;
Vector pos, direction, point0, point1;
pos = direction = point0 = point1 = kZeroVector;
if (routeFraction != NSNotFound && ([route isEqualTo:@"pw"] || [route isEqualTo:@"sw"] || [route isEqualTo:@"ps"]))
{
routeFraction = 1.0f - routeFraction;
}
// which route is it?
if ([route isEqualTo:@"wp"] || [route isEqualTo:@"pw"])
{
point0 = [self getWitchspaceExitPosition];
entity = [self planet];
if (!entity) return;
}
else if ([route isEqualTo:@"ws"] || [route isEqualTo:@"sw"])
{
point0 = [self getWitchspaceExitPosition];
entity = [self sun];
if (!entity) return;
}
else if ([route isEqualTo:@"sp"] || [route isEqualTo:@"ps"])
{
entity = [self sun];
if (!entity) return;
point0 = [entity position];
double radius0 = [entity radius];
entity = [self planet];
if (!entity) return;
point1 = [entity position];
// shorten the route by scanner range & sun radius, otherwise ships could be created inside it.
direction = vector_normal(vector_subtract(point0, point1));
point0 = vector_subtract(point0, vector_multiply_scalar(direction, radius0 + SCANNER_MAX_RANGE));
}
else return nil; // no route specifier? We shouldn't be here!
point1 = [entity position];
// shorten the route by scanner range & stellar body radius,, otherwise ships could be created inside it.
direction = vector_normal(vector_subtract(point1, point0));
point1 = vector_subtract(point1, vector_multiply_scalar(direction, [entity radius] + SCANNER_MAX_RANGE));
pos = [self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
if(isGroup)
{
return [self addShipsAt:pos withRole:role quantity:count withinRadius:SCANNER_MAX_RANGE asGroup:YES];
}
else
{
while (count--)
{
ship = [self addShipAt:pos withRole:role withinRadius:SCANNER_MAX_RANGE];
if (ship != nil) [ships addObject:ship];
if (count > 0) pos = [self fractionalPositionFrom:point0 to:point1 withFraction:routeFraction];
}
if ([ships count] == 0) return nil;
}
return [[ships copy] autorelease];
}
- (BOOL) roleIsPirateVictim:(NSString *)role
{
return [pirateVictimRoles containsObject:role];
@ -2583,10 +2740,10 @@ GLfloat docked_light_specular[4] = { DOCKED_ILLUM_LEVEL, DOCKED_ILLUM_LEVEL, DOC
[ship setScanClass: CLASS_NO_DRAW];
[ship setRoll:M_PI/5.0];
[ship setPitch:M_PI/10.0];
[[ship getAI] setStateMachine:@"nullAI.plist"];
[ship switchAITo:@"nullAI.plist"];
if([ship pendingEscortCount] > 0) [ship setPendingEscortCount:0];
[self addEntity:ship];
// set status here because addEntity may affect status
[self addEntity:ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
// now override status
[ship setStatus:STATUS_COCKPIT_DISPLAY];
demo_ship = ship;
if (justCobra==NO)
@ -3977,6 +4134,8 @@ static BOOL MaintainLinkedLists(Universe* uni)
{
if (entity)
{
ShipEntity* se = nil;
#ifndef NDEBUG
if (gDebugFlags & DEBUG_ENTITIES)
OOLog(@"universe.addEntity", @"Adding entity: %@", entity);
@ -4019,9 +4178,7 @@ static BOOL MaintainLinkedLists(Universe* uni)
entity_for_uid[next_universal_id] = entity;
if ([entity isShip])
{
ShipEntity* se = (ShipEntity *)entity;
[[se getAI] setOwner:se];
[[se getAI] setState:@"GLOBAL"];
se = (ShipEntity *)entity;
if ([se isBeacon])
{
[self setNextBeacon:se];
@ -4036,16 +4193,15 @@ static BOOL MaintainLinkedLists(Universe* uni)
double stationRoll = [systeminfo oo_doubleForKey:@"station_roll" defaultValue:0.4];
[se setRoll: stationRoll];
[(StationEntity *)se setPlanet:[self planet]];
[se setStatus:STATUS_ACTIVE];
}
else
{
[se setRoll: 0.0];
[(StationEntity *)se setPlanet:[self planet]];
[se setStatus:STATUS_ACTIVE];
}
[(StationEntity *)se setPlanet:[self planet]];
[se setStatus:STATUS_ACTIVE];
}
else [se setStatus:STATUS_IN_FLIGHT];
}
}
else
@ -4097,6 +4253,11 @@ static BOOL MaintainLinkedLists(Universe* uni)
{
[allPlanets addObject:entity];
}
else if ([entity isShip])
{
[[se getAI] setOwner:se];
[[se getAI] setState:@"GLOBAL"];
}
return YES;
}
@ -5307,9 +5468,10 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
if (demo_ship != nil)
{
[self addEntity:demo_ship];
[[demo_ship getAI] setStateMachine:@"nullAI.plist"];
[demo_ship switchAITo:@"nullAI.plist"];
[demo_ship setOrientation:q2];
[self addEntity:demo_ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
[demo_ship setStatus:STATUS_COCKPIT_DISPLAY];
demo_start_z=DEMO2_VANISHING_DISTANCE * demo_ship->collision_radius;
[demo_ship setPositionX:0.0f y:0.0f z:demo_start_z];
[demo_ship setDestination: make_vector(0.0f, 0.0f, demo_start_z * 0.01f)]; // ideal position
@ -5317,7 +5479,6 @@ OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
[demo_ship setScanClass: CLASS_NO_DRAW];
[demo_ship setRoll:M_PI/5.0];
[demo_ship setPitch:M_PI/10.0];
[demo_ship setStatus:STATUS_COCKPIT_DISPLAY];
[gui setText:shipName != nil ? shipName : [demo_ship displayName] forRow:19 align:GUI_ALIGN_CENTER];
demo_stage = DEMO_FLY_IN;
@ -8380,10 +8541,8 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context)
if (hunter_ship)
{
[hunter_ship setPosition:launchPos];
[hunter_ship setStatus:STATUS_IN_FLIGHT];
[hunter_ship setBounty:0];
[self addEntity:hunter_ship];
[self addEntity:hunter_ship]; // STATUS_IN_FLIGHT, AI state GLOBAL
[hunter_ship release]; // addEntity retains!
}
@ -8391,6 +8550,22 @@ static OOComparisonResult comparePrice(id dict1, id dict2, void * context)
}
- (Vector) fractionalPositionFrom:(Vector)point0 to:(Vector)point1 withFraction:(double)routeFraction
{
if (routeFraction == NSNotFound) routeFraction = randf();
point1.x -= point0.x; point1.y -= point0.y; point1.z -= point0.z;
point1.x *= routeFraction; point1.y *= routeFraction; point1.z *= routeFraction;
point1.x += point0.x; point1.y += point0.y; point1.z += point0.z;
point1.x += SCANNER_MAX_RANGE*(randf() - randf()); // TODO: coilt be done with just one randf()!
point1.y += SCANNER_MAX_RANGE*(randf() - randf());
point1.z += SCANNER_MAX_RANGE*(randf() - randf());
return point1;
}
- (BOOL)doRemoveEntity:(Entity *)entity
{
// remove reference to entity in linked lists