Most AI reactToMessage: calls now also have a script event; see http://www.aegidian.org/bb/viewtopic.php?p=47620#47620 . Some cleanup and optimization. Added command-line hack to graph difference between Vector.random() and Vector.randomDirectionAndLength() as in http://wiki.alioth.net/index.php/Image:Randomvectordistribution.png .
git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@1423 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
parent
0d0681de10
commit
e95e3fd521
@ -997,7 +997,7 @@
|
||||
083325DC09DDBCDE00F5B8E4 /* OOColor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOColor.m; sourceTree = "<group>"; };
|
||||
083DB4D30A70E51E00B419B2 /* OOBrain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OOBrain.h; sourceTree = "<group>"; };
|
||||
083DB4D40A70E51E00B419B2 /* OOBrain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OOBrain.m; sourceTree = "<group>"; };
|
||||
0865432206B8447D000CA0AB /* OoliteDev.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OoliteDev.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0865432206B8447D000CA0AB /* Oolite.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Oolite.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0878FD2F086EF845004CB752 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = "<absolute>"; };
|
||||
1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = "<absolute>"; };
|
||||
1A020E0A0D020AFB00C3F51E /* changedScriptHandlers.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist; path = changedScriptHandlers.plist; sourceTree = "<group>"; };
|
||||
@ -1649,7 +1649,7 @@
|
||||
19C28FACFE9D520D11CA2CBB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0865432206B8447D000CA0AB /* OoliteDev.app */,
|
||||
0865432206B8447D000CA0AB /* Oolite.app */,
|
||||
1A71E6F30BCE340C00CD5C13 /* libpng.a */,
|
||||
);
|
||||
name = Products;
|
||||
@ -2847,7 +2847,7 @@
|
||||
name = Oolite;
|
||||
productInstallPath = "$(HOME)/Applications";
|
||||
productName = Oolite;
|
||||
productReference = 0865432206B8447D000CA0AB /* OoliteDev.app */;
|
||||
productReference = 0865432206B8447D000CA0AB /* Oolite.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
1A71E6F20BCE340C00CD5C13 /* libpng-custom */ = {
|
||||
|
@ -332,9 +332,10 @@ typedef struct
|
||||
{
|
||||
if (currentState != nil)
|
||||
{
|
||||
SEL _interpretAIMessageSel = @selector(interpretAIMessage:);
|
||||
if ([owner respondsToSelector:_interpretAIMessageSel])
|
||||
[owner performSelector:_interpretAIMessageSel withObject:message];
|
||||
if ([owner respondsToSelector:@selector(interpretAIMessage:)])
|
||||
{
|
||||
[owner performSelector:@selector(interpretAIMessage:) withObject:message];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -890,7 +890,9 @@ FAIL:
|
||||
{
|
||||
Entity *e2 = [targets objectAtIndex:i];
|
||||
if (e2->isShip)
|
||||
[[(ShipEntity *)e2 getAI] reactToMessage:@"ECM"];
|
||||
{
|
||||
[(ShipEntity *)e2 doScriptEvent:@"shipHitByECM" andReactToAIMessage:@"ECM"];
|
||||
}
|
||||
}
|
||||
}
|
||||
activation_time += 0.5; // go off every half second
|
||||
|
@ -473,7 +473,7 @@ typedef enum
|
||||
isSpeechOn: 1,
|
||||
|
||||
keyboardRollPitchOverride: 1,
|
||||
waitingForStickCallback: 1;
|
||||
waitingForStickCallback: 1;
|
||||
|
||||
// Note: joystick stuff does nothing under OS X.
|
||||
// Keeping track of joysticks
|
||||
@ -615,6 +615,8 @@ typedef enum
|
||||
- (void) setGuiToIntro1Screen;
|
||||
- (void) setGuiToIntro2Screen;
|
||||
|
||||
- (void) noteGuiChangeFrom:(OOGUIScreenID)fromScreen to:(OOGUIScreenID)toScreen;
|
||||
|
||||
- (OOGUIScreenID) guiScreen;
|
||||
|
||||
- (void) buySelectedItem;
|
||||
|
@ -1279,10 +1279,13 @@ double scoopSoundPlayTime = 0.0;
|
||||
there turned out to be complications. See mailing list archive.
|
||||
-- Ahruman 20070802
|
||||
*/
|
||||
if ([self alertCondition] != lastScriptAlertCondition)
|
||||
OOAlertCondition cond = [self alertCondition];
|
||||
if (cond != lastScriptAlertCondition)
|
||||
{
|
||||
[self doScriptEvent:@"alertConditionChanged"];
|
||||
lastScriptAlertCondition = [self alertCondition];
|
||||
[self doScriptEvent:@"alertConditionChanged"
|
||||
withArgument:[NSNumber numberWithInt:cond]
|
||||
andArgument:[NSNumber numberWithInt:lastScriptAlertCondition]];
|
||||
lastScriptAlertCondition = cond;
|
||||
}
|
||||
|
||||
if (scoopsActive)
|
||||
@ -2717,7 +2720,7 @@ double scoopSoundPlayTime = 0.0;
|
||||
Quaternion q1 = orientation;
|
||||
q1.w = -q1.w; // player view is reversed remember!
|
||||
|
||||
Entity *target = [self primaryTarget];
|
||||
ShipEntity *target = [self primaryTarget];
|
||||
|
||||
// select a new active missile and decrease the missiles count
|
||||
missile_entity[activeMissile] = nil;
|
||||
@ -2757,9 +2760,10 @@ double scoopSoundPlayTime = 0.0;
|
||||
|
||||
[UNIVERSE addEntity:missile];
|
||||
[missile release];
|
||||
|
||||
[(ShipEntity *)target setPrimaryAggressor:self];
|
||||
[[(ShipEntity *)target getAI] reactToMessage:@"INCOMING_MISSILE"];
|
||||
|
||||
[target setPrimaryAggressor:self];
|
||||
[target doScriptEvent:@"shipAttackedWithMissile" withArgument:missile andArgument:self];
|
||||
[target reactToAIMessage:@"INCOMING_MISSILE"];
|
||||
|
||||
[UNIVERSE playCustomSound:@"[missile-launched]"];
|
||||
|
||||
@ -2957,9 +2961,10 @@ double scoopSoundPlayTime = 0.0;
|
||||
|
||||
if (status == STATUS_DEAD) return;
|
||||
if (amount == 0.0) return;
|
||||
|
||||
[ent retain];
|
||||
[other retain];
|
||||
|
||||
[[ent retain] autorelease];
|
||||
[[other retain] autorelease];
|
||||
|
||||
rel_pos = (ent != nil) ? [ent position] : kZeroVector;
|
||||
rel_pos = vector_subtract(rel_pos, position);
|
||||
|
||||
@ -3018,25 +3023,17 @@ double scoopSoundPlayTime = 0.0;
|
||||
|
||||
if (energy <= 0.0) //use normal ship temperature calculations for heat damage
|
||||
{
|
||||
if ((other)&&(other->isShip))
|
||||
if ([other isShip])
|
||||
{
|
||||
ShipEntity* hunter = (ShipEntity *)other;
|
||||
[hunter collectBountyFor:self];
|
||||
if ([hunter primaryTarget] == (Entity *)self)
|
||||
{
|
||||
[hunter removeTarget:(Entity *)self];
|
||||
[[hunter getAI] message:@"TARGET_DESTROYED"];
|
||||
}
|
||||
[(ShipEntity *)other noteTargetDestroyed:self];
|
||||
}
|
||||
|
||||
[self getDestroyedBy:other context:@"energy damage"];
|
||||
}
|
||||
|
||||
if (internal_damage) [self takeInternalDamage];
|
||||
|
||||
[ent release];
|
||||
[other release];
|
||||
|
||||
else
|
||||
{
|
||||
if (internal_damage) [self takeInternalDamage];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3049,14 +3046,10 @@ double scoopSoundPlayTime = 0.0;
|
||||
if (status == STATUS_DEAD)
|
||||
return;
|
||||
|
||||
[ent retain];
|
||||
rel_pos = (ent)? ent->position : kZeroVector;
|
||||
|
||||
rel_pos.x -= position.x;
|
||||
rel_pos.y -= position.y;
|
||||
rel_pos.z -= position.z;
|
||||
|
||||
d_forward = dot_product(rel_pos, v_forward);
|
||||
[[ent retain] autorelease];
|
||||
rel_pos = ent ? [ent position] : kZeroVector;
|
||||
rel_pos = vector_subtract(rel_pos, position);
|
||||
d_forward = dot_product(rel_pos, v_forward);
|
||||
|
||||
if (scrapeDamageSound)
|
||||
{
|
||||
@ -3089,31 +3082,27 @@ double scoopSoundPlayTime = 0.0;
|
||||
amount = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (amount)
|
||||
{
|
||||
internal_damage = ((ranrot_rand() & PLAYER_INTERNAL_DAMAGE_FACTOR) < amount); // base chance of damage to systems
|
||||
|
||||
}
|
||||
|
||||
energy -= amount;
|
||||
if (energy <= 0.0)
|
||||
{
|
||||
if ((ent)&&(ent->isShip))
|
||||
if ([ent isShip])
|
||||
{
|
||||
ShipEntity* hunter = (ShipEntity *)ent;
|
||||
[hunter collectBountyFor:self];
|
||||
if ([hunter primaryTarget] == (Entity *)self)
|
||||
{
|
||||
[hunter removeTarget:(Entity *)self];
|
||||
[[hunter getAI] message:@"TARGET_DESTROYED"];
|
||||
}
|
||||
[(ShipEntity *)ent noteTargetDestroyed:self];
|
||||
}
|
||||
|
||||
[self getDestroyedBy:ent context:@"scrape damage"];
|
||||
}
|
||||
|
||||
if (internal_damage) [self takeInternalDamage];
|
||||
|
||||
|
||||
[ent release];
|
||||
if (internal_damage)
|
||||
{
|
||||
[self takeInternalDamage];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3504,12 +3493,14 @@ double scoopSoundPlayTime = 0.0;
|
||||
ShipEntity* ship = (ShipEntity *)thing;
|
||||
if (self == [ship primaryTarget])
|
||||
{
|
||||
[[ship getAI] message:@"TARGET_LOST"];
|
||||
[ship noteLostTarget];
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ent_count; i++)
|
||||
{
|
||||
[my_entities[i] release]; // released
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3997,9 +3988,10 @@ double scoopSoundPlayTime = 0.0;
|
||||
[lastTextKey release];
|
||||
lastTextKey = nil;
|
||||
}
|
||||
|
||||
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
gui_screen = GUI_SCREEN_STATUS;
|
||||
|
||||
|
||||
[self setShowDemoShips: NO];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: NO];
|
||||
@ -4014,6 +4006,8 @@ double scoopSoundPlayTime = 0.0;
|
||||
[self setShowDemoShips: YES];
|
||||
// END TEST
|
||||
#endif
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
}
|
||||
|
||||
|
||||
@ -4107,14 +4101,14 @@ double scoopSoundPlayTime = 0.0;
|
||||
{
|
||||
NSDictionary* targetSystemData;
|
||||
NSString* targetSystemName;
|
||||
|
||||
|
||||
targetSystemData = [[UNIVERSE generateSystemData:target_system_seed] retain]; // retained
|
||||
targetSystemName = [[UNIVERSE getSystemName:target_system_seed] retain]; // retained
|
||||
|
||||
|
||||
BOOL sunGoneNova = NO;
|
||||
if ([targetSystemData objectForKey:@"sun_gone_nova"])
|
||||
sunGoneNova = YES;
|
||||
|
||||
|
||||
// GUI stuff
|
||||
{
|
||||
GuiDisplayGen* gui = [UNIVERSE gui];
|
||||
@ -4170,26 +4164,26 @@ double scoopSoundPlayTime = 0.0;
|
||||
|
||||
}
|
||||
/* ends */
|
||||
|
||||
if (lastTextKey)
|
||||
{
|
||||
[lastTextKey release];
|
||||
lastTextKey = nil;
|
||||
}
|
||||
|
||||
|
||||
[lastTextKey release];
|
||||
lastTextKey = nil;
|
||||
|
||||
[targetSystemData release];
|
||||
[targetSystemName release];
|
||||
|
||||
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
gui_screen = GUI_SCREEN_SYSTEM_DATA;
|
||||
|
||||
|
||||
[self setShowDemoShips: NO];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: NO];
|
||||
[UNIVERSE setViewDirection: VIEW_GUI_DISPLAY];
|
||||
|
||||
|
||||
[UNIVERSE removeDemoShips];
|
||||
[self setBackgroundFromDescriptionsKey:@"gui-scene-show-planet"];
|
||||
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
if (oldScreen != gui_screen) [self checkScript];
|
||||
}
|
||||
|
||||
|
||||
@ -4250,15 +4244,18 @@ double scoopSoundPlayTime = 0.0;
|
||||
[gui setCurrentRow:16];
|
||||
}
|
||||
/* ends */
|
||||
|
||||
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
gui_screen = GUI_SCREEN_LONG_RANGE_CHART;
|
||||
|
||||
|
||||
[targetSystemName release];
|
||||
|
||||
|
||||
[self setShowDemoShips: NO];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: YES];
|
||||
[UNIVERSE setViewDirection: VIEW_GUI_DISPLAY];
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
}
|
||||
|
||||
|
||||
@ -4290,21 +4287,21 @@ double scoopSoundPlayTime = 0.0;
|
||||
[gui setShowTextCursor:NO];
|
||||
}
|
||||
/* ends */
|
||||
|
||||
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
gui_screen = GUI_SCREEN_SHORT_RANGE_CHART;
|
||||
|
||||
|
||||
[targetSystemName release]; // released
|
||||
|
||||
|
||||
[self setShowDemoShips: NO];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: YES];
|
||||
[UNIVERSE setViewDirection: VIEW_GUI_DISPLAY];
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
- (void) setGuiToGameOptionsScreen
|
||||
{
|
||||
#ifdef GNUSTEP
|
||||
@ -5022,9 +5019,9 @@ static int last_outfitting_index;
|
||||
|
||||
- (void) setGuiToIntro2Screen
|
||||
{
|
||||
NSString *text;
|
||||
NSString *text = nil;
|
||||
GuiDisplayGen* gui = [UNIVERSE gui];
|
||||
|
||||
|
||||
[gui clear];
|
||||
[gui setTitle:@"Oolite"];
|
||||
|
||||
@ -5033,12 +5030,11 @@ static int last_outfitting_index;
|
||||
[gui setColor:[OOColor yellowColor] forRow:21];
|
||||
|
||||
[gui setShowTextCursor:NO];
|
||||
|
||||
|
||||
[UNIVERSE set_up_intro2];
|
||||
|
||||
if (gui)
|
||||
gui_screen = GUI_SCREEN_INTRO2;
|
||||
|
||||
|
||||
if (gui) gui_screen = GUI_SCREEN_INTRO2;
|
||||
|
||||
[self setShowDemoShips: YES];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: NO];
|
||||
@ -5046,6 +5042,17 @@ static int last_outfitting_index;
|
||||
}
|
||||
|
||||
|
||||
- (void) noteGuiChangeFrom:(OOGUIScreenID)fromScreen to:(OOGUIScreenID)toScreen
|
||||
{
|
||||
if (fromScreen != toScreen)
|
||||
{
|
||||
[self doScriptEvent:@"guiScreenChanged"
|
||||
withArgument:GUIScreenIDToString(toScreen)
|
||||
andArgument:GUIScreenIDToString(fromScreen)];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) buySelectedItem
|
||||
{
|
||||
GuiDisplayGen* gui = [UNIVERSE gui];
|
||||
@ -5053,7 +5060,7 @@ static int last_outfitting_index;
|
||||
|
||||
if ([key hasPrefix:@"More:"])
|
||||
{
|
||||
int from_item = [(NSString*)[[key componentsSeparatedByString:@":"] objectAtIndex:1] intValue];
|
||||
int from_item = [[key componentsSeparatedByString:@":"] intAtIndex:1];
|
||||
|
||||
[self setGuiToEquipShipScreen:from_item:-1];
|
||||
if ([gui selectedRow] < 0)
|
||||
@ -5369,7 +5376,7 @@ static int last_outfitting_index;
|
||||
// following works whether docked or not
|
||||
|
||||
for (i = 0; i < n_commodities; i++)
|
||||
in_hold[i] = [(NSNumber *)[(NSArray *)[shipCommodityData objectAtIndex:i] objectAtIndex:MARKET_QUANTITY] intValue];
|
||||
in_hold[i] = [[shipCommodityData arrayAtIndex:i] intAtIndex:MARKET_QUANTITY];
|
||||
for (i = 0; i < [cargo count]; i++)
|
||||
{
|
||||
ShipEntity *container = (ShipEntity *)[cargo objectAtIndex:i];
|
||||
@ -5380,8 +5387,10 @@ static int last_outfitting_index;
|
||||
|
||||
for (i = 0; i < n_commodities; i++)
|
||||
{
|
||||
if ([(NSNumber *)[(NSArray *)[shipCommodityData objectAtIndex:i] objectAtIndex:MARKET_UNITS] intValue] == UNITS_TONS)
|
||||
if ([[shipCommodityData arrayAtIndex:i] intAtIndex:MARKET_UNITS] == UNITS_TONS)
|
||||
{
|
||||
current_cargo += in_hold[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5493,13 +5502,16 @@ static int last_outfitting_index;
|
||||
|
||||
[gui setShowTextCursor:NO];
|
||||
}
|
||||
|
||||
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
gui_screen = GUI_SCREEN_MARKET;
|
||||
|
||||
|
||||
[self setShowDemoShips: NO];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: (status == STATUS_DOCKED)];
|
||||
[UNIVERSE setViewDirection: VIEW_GUI_DISPLAY];
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
}
|
||||
|
||||
|
||||
|
@ -685,12 +685,15 @@ static NSString * const kOOLogNoteShowShipyardModel = @"script.debug.note.showSh
|
||||
[gui setShowTextCursor:NO];
|
||||
}
|
||||
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
gui_screen = GUI_SCREEN_CONTRACTS;
|
||||
|
||||
[self setShowDemoShips: NO];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: YES];
|
||||
[UNIVERSE setViewDirection: VIEW_GUI_DISPLAY];
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
}
|
||||
|
||||
|
||||
@ -974,12 +977,15 @@ static NSString * const kOOLogNoteShowShipyardModel = @"script.debug.note.showSh
|
||||
lastTextKey = nil;
|
||||
}
|
||||
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
gui_screen = GUI_SCREEN_MANIFEST;
|
||||
|
||||
[self setShowDemoShips: NO];
|
||||
[UNIVERSE setDisplayText: YES];
|
||||
[UNIVERSE setDisplayCursor: NO];
|
||||
[UNIVERSE setViewDirection: VIEW_GUI_DISPLAY];
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
}
|
||||
|
||||
|
||||
|
@ -1380,7 +1380,6 @@ static NSTimeInterval time_last_frame;
|
||||
{
|
||||
[gameView clearMouse];
|
||||
[self setGuiToSystemDataScreen];
|
||||
[self checkScript];
|
||||
}
|
||||
if ([gameView isDown:key_map_home])
|
||||
{
|
||||
@ -2405,7 +2404,6 @@ static NSTimeInterval time_last_frame;
|
||||
if (gui_screen != GUI_SCREEN_SYSTEM_DATA)
|
||||
{
|
||||
[self setGuiToSystemDataScreen];
|
||||
[self checkScript];
|
||||
}
|
||||
}
|
||||
|
||||
@ -2422,8 +2420,9 @@ static NSTimeInterval time_last_frame;
|
||||
{
|
||||
if (!switching_equipship_screens)
|
||||
{
|
||||
if (!dockedStation)
|
||||
dockedStation = [UNIVERSE station];
|
||||
if (!dockedStation) dockedStation = [UNIVERSE station];
|
||||
OOGUIScreenID oldScreen = gui_screen;
|
||||
|
||||
if ((gui_screen == GUI_SCREEN_EQUIP_SHIP)&&[dockedStation hasShipyard])
|
||||
{
|
||||
[gameView clearKeys];
|
||||
@ -2437,6 +2436,8 @@ static NSTimeInterval time_last_frame;
|
||||
[self setGuiToEquipShipScreen:0:-1];
|
||||
[[UNIVERSE gui] setSelectedRow:GUI_ROW_EQUIPMENT_START];
|
||||
}
|
||||
|
||||
[self noteGuiChangeFrom:oldScreen to:gui_screen];
|
||||
}
|
||||
switching_equipship_screens = YES;
|
||||
}
|
||||
|
@ -1984,6 +1984,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
|
||||
[se1 setFuel: PLAYER_MAX_FUEL];
|
||||
[se1AI setStateMachine:@"exitingTraderAI.plist"];
|
||||
[se1AI setState:@"EXIT_SYSTEM"];
|
||||
// FIXME: I don't think the following line does anything meaningful.
|
||||
[se1AI reactToMessage:[NSString stringWithFormat:@"pauseAI: %d", 3 + (ranrot_rand() & 15)]];
|
||||
[se1 setPrimaryRole:@"none"]; // prevents new ship from appearing at witchpoint when this one leaves!
|
||||
}
|
||||
|
@ -285,8 +285,10 @@ MA 02110-1301, USA.
|
||||
// Collision detection
|
||||
Octree *octree;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// DEBUGGING
|
||||
OOBehaviour debug_condition;
|
||||
#endif
|
||||
|
||||
uint16_t entity_personality; // Per-entity random number. Exposed to shaders and scripts.
|
||||
NSDictionary *scriptInfo; // script_info dictionary from shipdata.plist, exposed to scripts.
|
||||
@ -543,6 +545,9 @@ BOOL class_masslocks(int some_class);
|
||||
- (id) primaryTarget;
|
||||
- (int) primaryTargetID;
|
||||
|
||||
- (void) noteLostTarget;
|
||||
- (void) noteTargetDestroyed:(ShipEntity *)target;
|
||||
|
||||
- (OOBehaviour) behaviour;
|
||||
- (void) setBehaviour:(OOBehaviour) cond;
|
||||
|
||||
@ -644,15 +649,15 @@ BOOL class_masslocks(int some_class);
|
||||
|
||||
- (int) checkShipsInVicinityForWitchJumpExit;
|
||||
|
||||
- (BOOL) trackCloseContacts;
|
||||
- (void) setTrackCloseContacts:(BOOL) value;
|
||||
|
||||
- (BOOL) isHulk;
|
||||
|
||||
/*
|
||||
* Changes a ship to a hulk, for example when the pilot ejects.
|
||||
* Aso unsets hulkiness for example when a new pilot gets in.
|
||||
*/
|
||||
- (void) setHulk:(BOOL) isNowHulk;
|
||||
- (BOOL) isHulk;
|
||||
- (void) claimAsSalvage;
|
||||
- (void) sendCoordinatesToPilot;
|
||||
- (void) pilotArrived;
|
||||
@ -666,8 +671,13 @@ BOOL class_masslocks(int some_class);
|
||||
// For the player, they do that and also call doWorldScriptEvent:.
|
||||
- (void) doScriptEvent:(NSString *)message;
|
||||
- (void) doScriptEvent:(NSString *)message withArgument:(id)argument;
|
||||
- (void) doScriptEvent:(NSString *)message withArgument:(id)argument1 andArgument:(id)argument2;
|
||||
- (void) doScriptEvent:(NSString *)message withArguments:(NSArray *)arguments;
|
||||
|
||||
- (void) reactToAIMessage:(NSString *)message;
|
||||
- (void) doScriptEvent:(NSString *)scriptEvent andReactToAIMessage:(NSString *)aiMessage;
|
||||
- (void) doScriptEvent:(NSString *)scriptEvent withArgument:(id)argument andReactToAIMessage:(NSString *)aiMessage;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -989,7 +989,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
// send AI a message about the touch
|
||||
int temp_id = primaryTarget;
|
||||
primaryTarget = other->universalID;
|
||||
[shipAI reactToMessage:@"CLOSE CONTACT"];
|
||||
[self doScriptEvent:@"shipCloseContact" withArgument:other andReactToAIMessage:@"CLOSE CONTACT"];
|
||||
primaryTarget = temp_id;
|
||||
}
|
||||
}
|
||||
@ -1112,12 +1112,10 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
ShipEntity* target = [UNIVERSE entityForUniversalID:primaryTarget];
|
||||
if ((target)&&(target->scanClass == CLASS_POLICE))
|
||||
{
|
||||
primaryTarget = NO_TARGET;
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
|
||||
if (trackCloseContacts)
|
||||
{
|
||||
// in checkCloseCollisionWith: we check if some thing has come within touch range (origin within our collision_radius)
|
||||
@ -1141,40 +1139,54 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
int temp_id = primaryTarget;
|
||||
primaryTarget = other->universalID;
|
||||
if ((pos0.x < 0.0)&&(pos1.x > 0.0))
|
||||
[shipAI reactToMessage:@"POSITIVE X TRAVERSE"];
|
||||
{
|
||||
[self doScriptEvent:@"shipTraversePositiveX" withArgument:other andReactToAIMessage:@"POSITIVE X TRAVERSE"];
|
||||
}
|
||||
if ((pos0.x > 0.0)&&(pos1.x < 0.0))
|
||||
[shipAI reactToMessage:@"NEGATIVE X TRAVERSE"];
|
||||
{
|
||||
[self doScriptEvent:@"shipTraverseNegativeX" withArgument:other andReactToAIMessage:@"NEGATIVE X TRAVERSE"];
|
||||
}
|
||||
if ((pos0.y < 0.0)&&(pos1.y > 0.0))
|
||||
[shipAI reactToMessage:@"POSITIVE Y TRAVERSE"];
|
||||
{
|
||||
[self doScriptEvent:@"shipTraversePositiveY" withArgument:other andReactToAIMessage:@"POSITIVE Y TRAVERSE"];
|
||||
}
|
||||
if ((pos0.y > 0.0)&&(pos1.y < 0.0))
|
||||
[shipAI reactToMessage:@"NEGATIVE Y TRAVERSE"];
|
||||
{
|
||||
[self doScriptEvent:@"shipTraverseNegativeY" withArgument:other andReactToAIMessage:@"NEGATIVE Y TRAVERSE"];
|
||||
}
|
||||
if ((pos0.z < 0.0)&&(pos1.z > 0.0))
|
||||
[shipAI reactToMessage:@"POSITIVE Z TRAVERSE"];
|
||||
{
|
||||
[self doScriptEvent:@"shipTraversePositiveZ" withArgument:other andReactToAIMessage:@"POSITIVE Z TRAVERSE"];
|
||||
}
|
||||
if ((pos0.z > 0.0)&&(pos1.z < 0.0))
|
||||
[shipAI reactToMessage:@"NEGATIVE Z TRAVERSE"];
|
||||
{
|
||||
[self doScriptEvent:@"shipTraverseNegativeZ" withArgument:other andReactToAIMessage:@"NEGATIVE Z TRAVERSE"];
|
||||
}
|
||||
primaryTarget = temp_id;
|
||||
[closeContactsInfo removeObjectForKey: other_key];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
[closeContactsInfo removeObjectForKey: other_key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// think!
|
||||
if (brain)
|
||||
[brain update:delta_t];
|
||||
|
||||
[brain update:delta_t];
|
||||
|
||||
// super update
|
||||
//
|
||||
[super update:delta_t];
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
// DEBUGGING
|
||||
if (reportAIMessages && (debug_condition != behaviour))
|
||||
{
|
||||
OOLog(kOOLogEntityBehaviourChanged, @"%@ behaviour is now %@", self, BehaviourToString(behaviour));
|
||||
debug_condition = behaviour;
|
||||
}
|
||||
#endif
|
||||
|
||||
// update time between shots
|
||||
//
|
||||
@ -1303,6 +1315,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
if (energy > maxEnergy)
|
||||
{
|
||||
energy = maxEnergy;
|
||||
[self doScriptEvent:@"shipEnergyBecameFull"];
|
||||
[shipAI message:@"ENERGY_FULL"];
|
||||
}
|
||||
}
|
||||
@ -1328,30 +1341,26 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
frustration = 0.0;
|
||||
}
|
||||
}
|
||||
//
|
||||
|
||||
if (status == STATUS_COCKPIT_DISPLAY)
|
||||
{
|
||||
[self applyRoll: delta_t * flightRoll andClimb: delta_t * flightPitch];
|
||||
GLfloat range2 = 0.1 * distance2(position, destination) / (collision_radius * collision_radius);
|
||||
if ((range2 > 1.0)||(velocity.z > 0.0)) range2 = 1.0;
|
||||
position.x += range2 * delta_t * velocity.x;
|
||||
position.y += range2 * delta_t * velocity.y;
|
||||
position.z += range2 * delta_t * velocity.z;
|
||||
// return; // here's our problem!
|
||||
position = vector_add(position, vector_multiply_scalar(velocity, range2 * delta_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
double target_speed = maxFlightSpeed;
|
||||
|
||||
|
||||
ShipEntity *target = [UNIVERSE entityForUniversalID:primaryTarget];
|
||||
|
||||
|
||||
if ((target == nil)||(target->scanClass == CLASS_NO_DRAW)||(!target->isShip)||([target isCloaked]))
|
||||
{
|
||||
// It's no longer a parrot, it has ceased to be, it has joined the choir invisible...
|
||||
if (primaryTarget != NO_TARGET)
|
||||
{
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
primaryTarget = NO_TARGET;
|
||||
[self noteLostTarget];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1549,12 +1558,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
{
|
||||
Entity *source = nil;
|
||||
|
||||
[shipAI reactToMessage:@"ATTACKED"];
|
||||
|
||||
if ([other isKindOfClass:[ShipEntity class]]) source = other;
|
||||
else source = from;
|
||||
|
||||
[self doScriptEvent:@"beingAttacked" withArgument:source];
|
||||
[shipAI reactToMessage:@"ATTACKED"];
|
||||
}
|
||||
|
||||
|
||||
@ -1578,7 +1586,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_idle:(double) delta_t
|
||||
{
|
||||
double damping = 0.5 * delta_t;
|
||||
@ -1601,13 +1610,15 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_tumble:(double) delta_t
|
||||
{
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_tractored:(double) delta_t
|
||||
{
|
||||
double distance = [self rangeToDestination];
|
||||
@ -1681,7 +1692,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyThrust:delta_t];
|
||||
thrust = 0.0; // must reset thrust now
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_track_target:(double) delta_t
|
||||
{
|
||||
[self trackPrimaryTarget:delta_t:NO];
|
||||
@ -1690,7 +1702,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_intercept_target:(double) delta_t
|
||||
{
|
||||
double range = [self rangeToPrimaryTarget];
|
||||
@ -1698,12 +1711,14 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
{
|
||||
desired_speed = maxFlightSpeed;
|
||||
if (range < desired_range)
|
||||
{
|
||||
[shipAI reactToMessage:@"DESIRED_RANGE_ACHIEVED"];
|
||||
}
|
||||
desired_speed = maxFlightSpeed * [self trackPrimaryTarget:delta_t:NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
ShipEntity* target = [UNIVERSE entityForUniversalID:primaryTarget];
|
||||
ShipEntity* target = [self primaryTarget];
|
||||
double target_speed = [target speed];
|
||||
double eta = range / (flightSpeed - target_speed);
|
||||
double last_success_factor = success_factor;
|
||||
@ -1723,12 +1738,14 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
{
|
||||
desired_speed += target_speed;
|
||||
if (target_speed > maxFlightSpeed)
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
{
|
||||
[self noteLostTarget];
|
||||
}
|
||||
}
|
||||
//
|
||||
if (target) // check introduced to stop crash at next line
|
||||
{
|
||||
destination = target->position; /* HEISENBUG crash here */
|
||||
destination = target->position;
|
||||
desired_range = 0.5 * target->collision_radius;
|
||||
[self trackDestination: delta_t : NO];
|
||||
}
|
||||
@ -1754,7 +1771,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_attack_target:(double) delta_t
|
||||
{
|
||||
BOOL canBurn = has_fuel_injection && (fuel > 1); // was &&(fuel > 0)
|
||||
@ -1780,25 +1798,27 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_fly_to_target_six:(double) delta_t
|
||||
{
|
||||
BOOL canBurn = has_fuel_injection && (fuel > 1); // was &&(fuel > 0)
|
||||
double max_available_speed = (canBurn)? maxFlightSpeed * AFTERBURNER_FACTOR : maxFlightSpeed;
|
||||
double range = [self rangeToPrimaryTarget];
|
||||
BOOL canBurn = has_fuel_injection && (fuel > 1); // was &&(fuel > 0)
|
||||
double max_available_speed = (canBurn)? maxFlightSpeed * AFTERBURNER_FACTOR : maxFlightSpeed;
|
||||
double range = [self rangeToPrimaryTarget];
|
||||
|
||||
// deal with collisions and lost targets
|
||||
//
|
||||
if (proximity_alert != NO_TARGET)
|
||||
{
|
||||
[self avoidCollision];
|
||||
}
|
||||
if (range > SCANNER_MAX_RANGE)
|
||||
{
|
||||
behaviour = BEHAVIOUR_IDLE;
|
||||
frustration = 0.0;
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
}
|
||||
|
||||
// control speed
|
||||
//
|
||||
BOOL isUsingAfterburner = canBurn && (flightSpeed > maxFlightSpeed);
|
||||
double slow_down_range = weaponRange * COMBAT_WEAPON_RANGE_FACTOR * ((isUsingAfterburner)? 3.0 * AFTERBURNER_FACTOR : 1.0);
|
||||
ShipEntity* target = [UNIVERSE entityForUniversalID:primaryTarget];
|
||||
@ -1807,8 +1827,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
if (range < slow_down_range)
|
||||
{
|
||||
desired_speed = OOMax_d(target_speed, 0.4 * maxFlightSpeed);
|
||||
|
||||
// avoid head-on collision
|
||||
//
|
||||
if ((range < 0.5 * distance)&&(behaviour == BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX))
|
||||
behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE;
|
||||
}
|
||||
@ -1817,7 +1837,6 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
|
||||
|
||||
// if within 0.75km of the target's six or twelve then vector in attack
|
||||
//
|
||||
if (distance < 750.0)
|
||||
{
|
||||
behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET;
|
||||
@ -1843,7 +1862,6 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self trackDestination:delta_t :NO];
|
||||
|
||||
// use weaponry
|
||||
//
|
||||
int missile_chance = 0;
|
||||
int rhs = 3.2 / delta_t;
|
||||
if (rhs) missile_chance = 1 + (ranrot_rand() % rhs);
|
||||
@ -1851,7 +1869,6 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
double hurt_factor = 16 * pow(energy/maxEnergy, 4.0);
|
||||
if (missiles > missile_chance * hurt_factor)
|
||||
{
|
||||
//NSLog(@"]==> firing missile : missiles %d, missile_chance %d, hurt_factor %.3f", missiles, missile_chance, hurt_factor);
|
||||
[self fireMissile];
|
||||
}
|
||||
[self activateCloakingDevice];
|
||||
@ -1859,7 +1876,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_attack_mining_target:(double) delta_t
|
||||
{
|
||||
double range = [self rangeToPrimaryTarget];
|
||||
@ -1876,11 +1894,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (range > SCANNER_MAX_RANGE)
|
||||
{
|
||||
behaviour = BEHAVIOUR_IDLE;
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
}
|
||||
if (range > SCANNER_MAX_RANGE) [self noteLostTarget];
|
||||
desired_speed = maxFlightSpeed * 0.375;
|
||||
}
|
||||
[self trackPrimaryTarget:delta_t:NO];
|
||||
@ -1888,7 +1902,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_attack_fly_to_target:(double) delta_t
|
||||
{
|
||||
BOOL canBurn = has_fuel_injection && (fuel > 1); // was &&(fuel > 0)
|
||||
@ -1927,7 +1942,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
{
|
||||
behaviour = BEHAVIOUR_IDLE;
|
||||
frustration = 0.0;
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1974,7 +1989,6 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
double hurt_factor = 16 * pow(energy/maxEnergy, 4.0);
|
||||
if (missiles > missile_chance * hurt_factor)
|
||||
{
|
||||
//NSLog(@"]==> firing missile : missiles %d, missile_chance %d, hurt_factor %.3f", missiles, missile_chance, hurt_factor);
|
||||
[self fireMissile];
|
||||
}
|
||||
[self activateCloakingDevice];
|
||||
@ -1982,7 +1996,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_attack_fly_from_target:(double) delta_t
|
||||
{
|
||||
double range = [self rangeToPrimaryTarget];
|
||||
@ -2003,14 +2018,14 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
double hurt_factor = 16 * pow(energy/maxEnergy, 4.0);
|
||||
if (missiles > missile_chance * hurt_factor)
|
||||
{
|
||||
//NSLog(@"]==> firing missile : missiles %d, missile_chance %d, hurt_factor %.3f", missiles, missile_chance, hurt_factor);
|
||||
[self fireMissile];
|
||||
}
|
||||
[self activateCloakingDevice];
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_running_defense:(double) delta_t
|
||||
{
|
||||
double range = [self rangeToPrimaryTarget];
|
||||
@ -2028,10 +2043,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_flee_target:(double) delta_t
|
||||
{
|
||||
BOOL canBurn = has_fuel_injection && (fuel > 1); // was &&(fuel > 0)
|
||||
BOOL canBurn = has_fuel_injection && (fuel > 1);
|
||||
double max_available_speed = (canBurn)? maxFlightSpeed * AFTERBURNER_FACTOR : maxFlightSpeed;
|
||||
double range = [self rangeToPrimaryTarget];
|
||||
if (range > desired_range)
|
||||
@ -2060,19 +2076,25 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_fly_range_from_destination:(double) delta_t
|
||||
{
|
||||
double distance = [self rangeToDestination];
|
||||
if (distance < desired_range)
|
||||
{
|
||||
behaviour = BEHAVIOUR_FLY_FROM_DESTINATION;
|
||||
}
|
||||
else
|
||||
{
|
||||
behaviour = BEHAVIOUR_FLY_TO_DESTINATION;
|
||||
}
|
||||
frustration = 0.0;
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_face_destination:(double) delta_t
|
||||
{
|
||||
double max_cos = 0.995;
|
||||
@ -2095,7 +2117,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_formation_form_up:(double) delta_t
|
||||
{
|
||||
// get updated destination from owner
|
||||
@ -2108,7 +2131,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
desired_speed = maxFlightSpeed;
|
||||
[self behaviour_fly_to_destination: delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_fly_to_destination:(double) delta_t
|
||||
{
|
||||
double distance = [self rangeToDestination];
|
||||
@ -2157,7 +2181,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_fly_from_destination:(double) delta_t
|
||||
{
|
||||
double distance = [self rangeToDestination];
|
||||
@ -2179,7 +2204,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_avoid_collision:(double) delta_t
|
||||
{
|
||||
double distance = [self rangeToDestination];
|
||||
@ -2205,7 +2231,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyRoll:delta_t*flightRoll andClimb:delta_t*flightPitch];
|
||||
[self applyThrust:delta_t];
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_track_as_turret:(double) delta_t
|
||||
{
|
||||
double aim = [self ballTrackLeadingTarget:delta_t];
|
||||
@ -2222,7 +2249,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self fireTurretCannon: sqrt(magnitude2(p1)) - cr];
|
||||
}
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_fly_thru_navpoints:(double) delta_t
|
||||
{
|
||||
int navpoint_plus_index = (next_navpoint_index + 1) % number_of_navpoints;
|
||||
@ -2255,10 +2283,10 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
if (dist2 < desired_range * desired_range)
|
||||
{
|
||||
// desired range achieved
|
||||
[shipAI reactToMessage:@"NAVPOINT_REACHED"];
|
||||
[self doScriptEvent:@"shipReachedNavPoint" andReactToAIMessage:@"NAVPOINT_REACHED"];
|
||||
if (navpoint_plus_index == 0)
|
||||
{
|
||||
[shipAI reactToMessage:@"ENDPOINT_REACHED"];
|
||||
[self doScriptEvent:@"shipReachedEndPoint" andReactToAIMessage:@"ENDPOINT_REACHED"];
|
||||
behaviour = BEHAVIOUR_IDLE;
|
||||
}
|
||||
next_navpoint_index = navpoint_plus_index; // loop as required
|
||||
@ -2306,7 +2334,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
[self applyThrust:delta_t];
|
||||
desired_speed = temp;
|
||||
}
|
||||
// //
|
||||
|
||||
|
||||
- (void) behaviour_experimental:(double) delta_t
|
||||
{
|
||||
double aim = [self ballTrackTarget:delta_t];
|
||||
@ -2315,8 +2344,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
|
||||
OOLog(@"behaviour.experimental.foundTarget", @"DEBUG BANG! BANG! BANG!");
|
||||
}
|
||||
}
|
||||
// //
|
||||
////////////////
|
||||
|
||||
|
||||
// override Entity saveToLastFrame
|
||||
//
|
||||
@ -4427,9 +4455,8 @@ BOOL class_masslocks(int some_class)
|
||||
|
||||
- (void) removeTarget:(Entity *) targetEntity
|
||||
{
|
||||
if (primaryTarget != NO_TARGET)
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
primaryTarget = NO_TARGET;
|
||||
[self noteLostTarget];
|
||||
|
||||
if (sub_entities)
|
||||
{
|
||||
unsigned i;
|
||||
@ -4437,7 +4464,9 @@ BOOL class_masslocks(int some_class)
|
||||
{
|
||||
Entity* se = [sub_entities objectAtIndex:i];
|
||||
if (se->isShip)
|
||||
{
|
||||
[(ShipEntity *)se removeTarget:targetEntity];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4455,6 +4484,29 @@ BOOL class_masslocks(int some_class)
|
||||
}
|
||||
|
||||
|
||||
- (void) noteLostTarget
|
||||
{
|
||||
if (primaryTarget != NO_TARGET)
|
||||
{
|
||||
primaryTarget = NO_TARGET;
|
||||
[self doScriptEvent:@"shipLostTarget"];
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void) noteTargetDestroyed:(ShipEntity *)target
|
||||
{
|
||||
[self collectBountyFor:(ShipEntity *)target];
|
||||
if ([self primaryTarget] == target)
|
||||
{
|
||||
[self removeTarget:target];
|
||||
[self doScriptEvent:@"shipDestroyedTarget" withArgument:target];
|
||||
[shipAI message:@"TARGET_DESTROYED"];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (OOBehaviour) behaviour
|
||||
{
|
||||
return behaviour;
|
||||
@ -4652,7 +4704,7 @@ BOOL class_masslocks(int some_class)
|
||||
|
||||
if (!target) // leave now!
|
||||
{
|
||||
[shipAI message:@"TARGET_LOST"];
|
||||
[self noteLostTarget]; // NOTE: was AI message: rather than reactToMessage:
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -4666,7 +4718,7 @@ BOOL class_masslocks(int some_class)
|
||||
|
||||
if (range2 > SCANNER_MAX_RANGE2)
|
||||
{
|
||||
[shipAI message:@"TARGET_LOST"];
|
||||
[self noteLostTarget]; // NOTE: was AI message: rather than reactToMessage:
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
@ -5736,7 +5788,8 @@ BOOL class_masslocks(int some_class)
|
||||
if ([missile scanClass] == CLASS_MISSILE)
|
||||
{
|
||||
[target_ship setPrimaryAggressor:self];
|
||||
[[target_ship getAI] reactToMessage:@"INCOMING_MISSILE"];
|
||||
[target_ship doScriptEvent:@"shipAttackedWithMissile" withArgument:missile andArgument:self];
|
||||
[target_ship reactToAIMessage:@"INCOMING_MISSILE"];
|
||||
}
|
||||
|
||||
return YES;
|
||||
@ -6181,12 +6234,12 @@ BOOL class_masslocks(int some_class)
|
||||
[other setPosition:pos2a];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// remove self from other's collision list
|
||||
[[other collisionArray] removeObject:self];
|
||||
|
||||
[shipAI reactToMessage:@"COLLISION"];
|
||||
|
||||
|
||||
[self doScriptEvent:@"shipCollided" withArgument:other andReactToAIMessage:@"COLLISION"];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
@ -6488,24 +6541,19 @@ BOOL class_masslocks(int some_class)
|
||||
// die if I'm out of energy
|
||||
if (energy <= 0.0)
|
||||
{
|
||||
if (hunter != nil)
|
||||
{
|
||||
[hunter collectBountyFor:self];
|
||||
if ([hunter primaryTarget] == self)
|
||||
{
|
||||
[hunter removeTarget:self];
|
||||
[[hunter getAI] message:@"TARGET_DESTROYED"];
|
||||
}
|
||||
}
|
||||
[hunter noteTargetDestroyed:self];
|
||||
[self getDestroyedBy:other context:@"energy damage"];
|
||||
}
|
||||
else
|
||||
{
|
||||
// warn if I'm low on energy
|
||||
if (energy < maxEnergy *0.25)
|
||||
[shipAI reactToMessage:@"ENERGY_LOW"];
|
||||
if ((energy < maxEnergy *0.125)&&(has_escape_pod)&&((ranrot_rand() & 3) == 0)) // 25% chance he gets to an escape pod
|
||||
if (energy < maxEnergy * 0.25)
|
||||
{
|
||||
[self doScriptEvent:@"shipEnergyIsLow" andReactToAIMessage:@"ENERGY_LOW"];
|
||||
}
|
||||
if (energy < maxEnergy *0.125 && has_escape_pod && (ranrot_rand() & 3) == 0) // 25% chance he gets to an escape pod
|
||||
{
|
||||
// TODO: abandoning ship should be split out into a separate method.
|
||||
has_escape_pod = NO;
|
||||
|
||||
[shipAI setStateMachine:@"nullAI.plist"];
|
||||
@ -6537,23 +6585,19 @@ BOOL class_masslocks(int some_class)
|
||||
if (energy <= 0.0)
|
||||
{
|
||||
being_mined = YES; // same as using a mining laser
|
||||
if ((ent)&&(ent->isShip))
|
||||
if ([ent isShip])
|
||||
{
|
||||
ShipEntity* hunter = (ShipEntity *)ent;
|
||||
[hunter collectBountyFor:self];
|
||||
if ([hunter primaryTarget] == (Entity *)self)
|
||||
{
|
||||
[hunter removeTarget:(Entity *)self];
|
||||
[[hunter getAI] message:@"TARGET_DESTROYED"];
|
||||
}
|
||||
[(ShipEntity *)ent noteTargetDestroyed:self];
|
||||
}
|
||||
[self getDestroyedBy:ent context:@"scrape damage"];
|
||||
}
|
||||
else
|
||||
{
|
||||
// warn if I'm low on energy
|
||||
if (energy < maxEnergy *0.25)
|
||||
[shipAI message:@"ENERGY_LOW"];
|
||||
if (energy < maxEnergy * 0.25)
|
||||
{
|
||||
[self doScriptEvent:@"shipEnergyIsLow" andReactToAIMessage:@"ENERGY_LOW"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6576,8 +6620,10 @@ BOOL class_masslocks(int some_class)
|
||||
else
|
||||
{
|
||||
// warn if I'm low on energy
|
||||
if (energy < maxEnergy *0.25)
|
||||
[shipAI message:@"ENERGY_LOW"];
|
||||
if (energy < maxEnergy * 0.25)
|
||||
{
|
||||
[self doScriptEvent:@"shipEnergyIsLow" andReactToAIMessage:@"ENERGY_LOW"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7057,15 +7103,35 @@ int w_space_seed = 1234567;
|
||||
}
|
||||
|
||||
|
||||
- (void) broadcastHitByLaserFrom:(ShipEntity*) aggressor_ship
|
||||
static BOOL AuthorityPredicate(Entity *entity, void *parameter)
|
||||
{
|
||||
ShipEntity *victim = parameter;
|
||||
|
||||
// Select main station, if victim is in aegis
|
||||
if (entity == [UNIVERSE station] && [victim withinStationAegis])
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Select police units in scanner range
|
||||
if ([entity scanClass] == CLASS_POLICE &&
|
||||
distance2([victim position], [entity position]) < SCANNER_MAX_RANGE2)
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
// Reject others
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
- (void) broadcastHitByLaserFrom:(ShipEntity *) aggressor_ship
|
||||
{
|
||||
/*-- If you're clean, locates all police and stations in range and tells them OFFENCE_COMMITTED --*/
|
||||
if (!UNIVERSE)
|
||||
return;
|
||||
if (bounty)
|
||||
return;
|
||||
if (!aggressor_ship)
|
||||
return;
|
||||
if (!UNIVERSE) return;
|
||||
if (bounty) return;
|
||||
if (!aggressor_ship) return;
|
||||
|
||||
if ( (scanClass == CLASS_NEUTRAL)||
|
||||
(scanClass == CLASS_STATION)||
|
||||
(scanClass == CLASS_BUOY)||
|
||||
@ -7073,25 +7139,20 @@ int w_space_seed = 1234567;
|
||||
(scanClass == CLASS_MILITARY)||
|
||||
(scanClass == CLASS_PLAYER)) // only for active ships...
|
||||
{
|
||||
int ent_count = UNIVERSE->n_entities;
|
||||
Entity** uni_entities = UNIVERSE->sortedEntities; // grab the public sorted list
|
||||
Entity* my_entities[ent_count];
|
||||
int i;
|
||||
int ship_count = 0;
|
||||
StationEntity* mainStation = [UNIVERSE station];
|
||||
for (i = 0; i < ent_count; i++)
|
||||
if ((uni_entities[i]->isShip)&&((uni_entities[i]->scanClass == CLASS_POLICE)||(uni_entities[i] == mainStation)))
|
||||
my_entities[ship_count++] = [uni_entities[i] retain]; // retained
|
||||
//
|
||||
for (i = 0; i < ship_count ; i++)
|
||||
NSArray *authorities = nil;
|
||||
NSEnumerator *authEnum = nil;
|
||||
ShipEntity *auth = nil;
|
||||
|
||||
authorities = [UNIVERSE findShipsMatchingPredicate:AuthorityPredicate
|
||||
parameter:self
|
||||
inRange:-1
|
||||
ofEntity:nil];
|
||||
authEnum = [authorities objectEnumerator];
|
||||
while ((auth = [authEnum nextObject]))
|
||||
{
|
||||
ShipEntity* ship = (ShipEntity *)my_entities[i];
|
||||
if (((ship == mainStation) && ([self withinStationAegis])) || (distance2(position, ship->position) < SCANNER_MAX_RANGE2))
|
||||
{
|
||||
[ship setFound_target: aggressor_ship];
|
||||
[[ship getAI] reactToMessage: @"OFFENCE_COMMITTED"];
|
||||
}
|
||||
[my_entities[i] release]; // released
|
||||
[auth setFound_target:aggressor_ship];
|
||||
[auth doScriptEvent:@"offenceCommittedNearby" withArgument:aggressor_ship andArgument:self];
|
||||
[auth reactToAIMessage:@"OFFENCE_COMMITTED"];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7322,21 +7383,25 @@ int w_space_seed = 1234567;
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) trackCloseContacts
|
||||
{
|
||||
return trackCloseContacts;
|
||||
}
|
||||
|
||||
|
||||
- (void) setTrackCloseContacts:(BOOL) value
|
||||
{
|
||||
if (value == trackCloseContacts)
|
||||
return;
|
||||
if (value == trackCloseContacts) return;
|
||||
|
||||
trackCloseContacts = value;
|
||||
[closeContactsInfo release];
|
||||
|
||||
if (trackCloseContacts)
|
||||
{
|
||||
if (closeContactsInfo)
|
||||
[closeContactsInfo removeAllObjects];
|
||||
else
|
||||
closeContactsInfo = [[NSMutableDictionary alloc] init];
|
||||
closeContactsInfo = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
else
|
||||
{
|
||||
[closeContactsInfo release];
|
||||
closeContactsInfo = nil;
|
||||
}
|
||||
}
|
||||
@ -7537,7 +7602,24 @@ int w_space_seed = 1234567;
|
||||
- (void) doScriptEvent:(NSString *)message withArgument:(id)argument
|
||||
{
|
||||
NSArray *arguments = nil;
|
||||
if (argument != nil) arguments = [NSArray arrayWithObject:argument];
|
||||
|
||||
if (argument == nil) argument = [NSNull null];
|
||||
arguments = [NSArray arrayWithObject:argument];
|
||||
|
||||
[self doScriptEvent:message withArguments:arguments];
|
||||
}
|
||||
|
||||
|
||||
- (void) doScriptEvent:(NSString *)message
|
||||
withArgument:(id)argument1
|
||||
andArgument:(id)argument2
|
||||
{
|
||||
NSArray *arguments = nil;
|
||||
|
||||
if (argument1 == nil) argument1 = [NSNull null];
|
||||
if (argument2 == nil) argument2 = [NSNull null];
|
||||
arguments = [NSArray arrayWithObjects:argument1, argument2, nil];
|
||||
|
||||
[self doScriptEvent:message withArguments:arguments];
|
||||
}
|
||||
|
||||
@ -7547,6 +7629,26 @@ int w_space_seed = 1234567;
|
||||
[script doEvent:message withArguments:arguments];
|
||||
}
|
||||
|
||||
|
||||
- (void) reactToAIMessage:(NSString *)message
|
||||
{
|
||||
[shipAI reactToMessage:message];
|
||||
}
|
||||
|
||||
|
||||
- (void) doScriptEvent:(NSString *)scriptEvent andReactToAIMessage:(NSString *)aiMessage
|
||||
{
|
||||
[self doScriptEvent:scriptEvent];
|
||||
[self reactToAIMessage:aiMessage];
|
||||
}
|
||||
|
||||
|
||||
- (void) doScriptEvent:(NSString *)scriptEvent withArgument:(id)argument andReactToAIMessage:(NSString *)aiMessage
|
||||
{
|
||||
[self doScriptEvent:scriptEvent withArgument:argument];
|
||||
[self reactToAIMessage:aiMessage];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -956,11 +956,7 @@ WormholeEntity* whole;
|
||||
for (i = 0; i < ent_count; i++) if (uni_entities[i]->isShip)
|
||||
{
|
||||
ShipEntity *other = (ShipEntity*)uni_entities[i];
|
||||
if ([other primaryTarget] == self)
|
||||
{
|
||||
[[other getAI] message:@"TARGET_LOST"]; // lose targetting
|
||||
other->primaryTarget = NO_TARGET;
|
||||
}
|
||||
[other removeTarget:self];
|
||||
}
|
||||
// now we're just a bunch of alien artefacts!
|
||||
scanClass = CLASS_CARGO;
|
||||
@ -1342,8 +1338,7 @@ WormholeEntity* whole;
|
||||
ShipEntity *ship = [self primaryTarget];
|
||||
if ((ship == nil) || (ship->status == STATUS_DEAD) || (ship->status == STATUS_DOCKED))
|
||||
{
|
||||
primaryTarget = NO_TARGET;
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
return;
|
||||
}
|
||||
[self sendExpandedMessage:message toShip:[self primaryTarget]];
|
||||
@ -1355,8 +1350,7 @@ WormholeEntity* whole;
|
||||
ShipEntity *ship = [self primaryTarget];
|
||||
if ((ship == nil) || (ship->status == STATUS_DEAD) || (ship->status == STATUS_DOCKED))
|
||||
{
|
||||
primaryTarget = NO_TARGET;
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
return;
|
||||
}
|
||||
if ([ship markForFines]) [shipAI message:@"TARGET_MARKED"];
|
||||
@ -1370,8 +1364,7 @@ WormholeEntity* whole;
|
||||
ShipEntity *ship = [self primaryTarget];
|
||||
if ((ship == nil) || (ship->status == STATUS_DEAD) || (ship->status == STATUS_DOCKED))
|
||||
{
|
||||
primaryTarget = NO_TARGET;
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
return;
|
||||
}
|
||||
NSString* finalValue = ExpandDescriptionForCurrentSystem(valueString); // expand values
|
||||
|
@ -29,9 +29,9 @@ MA 02110-1301, USA.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATION_ALERT_LEVEL_GREEN,
|
||||
STATION_ALERT_LEVEL_YELLOW,
|
||||
STATION_ALERT_LEVEL_RED
|
||||
STATION_ALERT_LEVEL_GREEN = ALERT_CONDITION_GREEN,
|
||||
STATION_ALERT_LEVEL_YELLOW = ALERT_CONDITION_YELLOW,
|
||||
STATION_ALERT_LEVEL_RED = ALERT_CONDITION_RED
|
||||
} OOStationAlertLevel;
|
||||
|
||||
#define STATION_MAX_POLICE 8
|
||||
@ -48,7 +48,7 @@ typedef enum
|
||||
NSMutableArray *launchQueue;
|
||||
double last_launch_time;
|
||||
double approach_spacing;
|
||||
OOStationAlertLevel alert_level;
|
||||
OOStationAlertLevel alertLevel;
|
||||
|
||||
OOUniversalID id_lock[MAX_DOCKING_STAGES]; // ship id's or NO_TARGET's
|
||||
|
||||
@ -154,29 +154,23 @@ typedef enum
|
||||
- (BOOL)hasNPCTraffic;
|
||||
- (void)setHasNPCTraffic:(BOOL)flag;
|
||||
|
||||
- (OOStationAlertLevel) alertLevel;
|
||||
- (void) setAlertLevel:(OOStationAlertLevel)level signallingScript:(BOOL)signallingScript;
|
||||
|
||||
////////////////////////////////////////////////////////////// AI methods...
|
||||
|
||||
- (void) increaseAlertLevel;
|
||||
|
||||
- (void) decreaseAlertLevel;
|
||||
|
||||
- (void) launchPolice;
|
||||
|
||||
- (void) launchDefenseShip;
|
||||
|
||||
- (void) launchScavenger;
|
||||
|
||||
- (void) launchMiner;
|
||||
|
||||
/**Lazygun** added the following line*/
|
||||
- (void) launchPirateShip;
|
||||
|
||||
- (void) launchShuttle;
|
||||
|
||||
- (void) launchTrader;
|
||||
|
||||
- (void) launchEscort;
|
||||
|
||||
- (BOOL) launchPatrol;
|
||||
|
||||
- (void) launchShipWithRole:(NSString*) role;
|
||||
@ -186,7 +180,6 @@ typedef enum
|
||||
- (void) acceptDockingClearanceRequestFrom:(ShipEntity *)other;
|
||||
|
||||
- (BOOL) isRotatingStation;
|
||||
|
||||
- (BOOL) hasShipyard;
|
||||
|
||||
@end
|
||||
|
@ -698,6 +698,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
|
||||
|
||||
isShip = YES;
|
||||
isStation = YES;
|
||||
alertLevel = STATION_ALERT_LEVEL_GREEN;
|
||||
|
||||
// ** Set up a the docking port
|
||||
// Look for subentity specifying position
|
||||
@ -1222,7 +1223,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
|
||||
int old_behaviour = [(NSNumber*)[previousCondition objectForKey:@"behaviour"] intValue];
|
||||
return IsBehaviourHostile(old_behaviour);
|
||||
}
|
||||
return IsBehaviourHostile(behaviour)||(alert_level == STATION_ALERT_LEVEL_YELLOW)||(alert_level == STATION_ALERT_LEVEL_RED);
|
||||
return IsBehaviourHostile(behaviour)||(alertLevel == STATION_ALERT_LEVEL_YELLOW)||(alertLevel == STATION_ALERT_LEVEL_RED);
|
||||
}
|
||||
|
||||
|
||||
@ -1271,76 +1272,94 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
|
||||
if (self != [UNIVERSE station]) [super takeHeatDamage:amount];
|
||||
}
|
||||
|
||||
|
||||
- (OOStationAlertLevel) alertLevel
|
||||
{
|
||||
return alertLevel;
|
||||
}
|
||||
|
||||
|
||||
- (void) setAlertLevel:(OOStationAlertLevel)level signallingScript:(BOOL)signallingScript
|
||||
{
|
||||
if (level < STATION_ALERT_LEVEL_GREEN) level = STATION_ALERT_LEVEL_GREEN;
|
||||
if (level > STATION_ALERT_LEVEL_RED) level = STATION_ALERT_LEVEL_RED;
|
||||
|
||||
if (alertLevel != level)
|
||||
{
|
||||
OOStationAlertLevel oldLevel = alertLevel;
|
||||
alertLevel = level;
|
||||
if (signallingScript)
|
||||
{
|
||||
[self doScriptEvent:@"alertConditionChanged"
|
||||
withArgument:[NSNumber numberWithUnsignedInt:level]
|
||||
andArgument:[NSNumber numberWithUnsignedInt:oldLevel]];
|
||||
}
|
||||
switch (level)
|
||||
{
|
||||
case STATION_ALERT_LEVEL_GREEN:
|
||||
[shipAI reactToMessage:@"GREEN_ALERT"];
|
||||
break;
|
||||
|
||||
case STATION_ALERT_LEVEL_YELLOW:
|
||||
[shipAI reactToMessage:@"YELLOW_ALERT"];
|
||||
break;
|
||||
|
||||
case STATION_ALERT_LEVEL_RED:
|
||||
[shipAI reactToMessage:@"RED_ALERT"];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////// extra AI routines
|
||||
|
||||
|
||||
- (void) increaseAlertLevel
|
||||
{
|
||||
switch (alert_level)
|
||||
{
|
||||
case STATION_ALERT_LEVEL_GREEN :
|
||||
alert_level = STATION_ALERT_LEVEL_YELLOW;
|
||||
[shipAI reactToMessage:@"YELLOW_ALERT"];
|
||||
break;
|
||||
|
||||
case STATION_ALERT_LEVEL_YELLOW :
|
||||
alert_level = STATION_ALERT_LEVEL_RED;
|
||||
[shipAI reactToMessage:@"RED_ALERT"];
|
||||
break;
|
||||
|
||||
case STATION_ALERT_LEVEL_RED:
|
||||
break;
|
||||
}
|
||||
[self setAlertLevel:[self alertLevel] + 1 signallingScript:YES];
|
||||
}
|
||||
|
||||
|
||||
- (void) decreaseAlertLevel
|
||||
{
|
||||
switch (alert_level)
|
||||
{
|
||||
case STATION_ALERT_LEVEL_RED :
|
||||
alert_level = STATION_ALERT_LEVEL_YELLOW;
|
||||
[shipAI reactToMessage:@"CONDITION_YELLOW"];
|
||||
break;
|
||||
|
||||
case STATION_ALERT_LEVEL_YELLOW :
|
||||
alert_level = STATION_ALERT_LEVEL_GREEN;
|
||||
[shipAI reactToMessage:@"CONDITION_GREEN"];
|
||||
break;
|
||||
|
||||
case STATION_ALERT_LEVEL_GREEN:
|
||||
break;
|
||||
}
|
||||
[self setAlertLevel:[self alertLevel] - 1 signallingScript:YES];
|
||||
}
|
||||
|
||||
|
||||
- (void) launchPolice
|
||||
{
|
||||
OOTechLevelID techlevel = [self equivalentTechLevel];
|
||||
if (techlevel == NSNotFound)
|
||||
techlevel = 6;
|
||||
int police_target = primaryTarget;
|
||||
unsigned i;
|
||||
OOUniversalID police_target = primaryTarget;
|
||||
unsigned i;
|
||||
OOTechLevelID techlevel = [self equivalentTechLevel];
|
||||
if (techlevel == NSNotFound) techlevel = 6;
|
||||
|
||||
for (i = 0; (i < 4)&&(police_launched < max_police) ; i++)
|
||||
{
|
||||
ShipEntity *police_ship;
|
||||
ShipEntity *police_ship = nil;
|
||||
if (![UNIVERSE entityForUniversalID:police_target])
|
||||
{
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Ranrot() & 7) + 6 <= techlevel)
|
||||
{
|
||||
police_ship = [UNIVERSE newShipWithRole:@"interceptor"]; // retain count = 1
|
||||
}
|
||||
else
|
||||
{
|
||||
police_ship = [UNIVERSE newShipWithRole:@"police"]; // retain count = 1
|
||||
}
|
||||
|
||||
if (police_ship)
|
||||
{
|
||||
if (![police_ship crew])
|
||||
{
|
||||
[police_ship setCrew:[NSArray arrayWithObject:
|
||||
[OOCharacter randomCharacterWithRole: @"police"
|
||||
andOriginalSystem: [UNIVERSE systemSeed]]]];
|
||||
|
||||
andOriginalSystem: [UNIVERSE systemSeed]]]];
|
||||
}
|
||||
|
||||
[police_ship setPrimaryRole:@"police"];
|
||||
[police_ship addTarget:[UNIVERSE entityForUniversalID:police_target]];
|
||||
[police_ship setScanClass: CLASS_POLICE];
|
||||
@ -1376,7 +1395,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
|
||||
|
||||
if (![UNIVERSE entityForUniversalID:defense_target])
|
||||
{
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1491,13 +1510,14 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
|
||||
- (void) launchPirateShip
|
||||
{
|
||||
//Pirate ships are launched from the same pool as defence ships.
|
||||
int defense_target = primaryTarget;
|
||||
ShipEntity *pirate_ship;
|
||||
if (police_launched >= max_defense_ships) // shuttles are to rockhermits what police ships are to stations
|
||||
return;
|
||||
OOUniversalID defense_target = primaryTarget;
|
||||
ShipEntity *pirate_ship = nil;
|
||||
|
||||
if (police_launched >= max_defense_ships) return; // shuttles are to rockhermits what police ships are to stations
|
||||
|
||||
if (![UNIVERSE entityForUniversalID:defense_target])
|
||||
{
|
||||
[shipAI reactToMessage:@"TARGET_LOST"];
|
||||
[self noteLostTarget];
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1510,9 +1530,11 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
|
||||
if (pirate_ship)
|
||||
{
|
||||
if (![pirate_ship crew])
|
||||
{
|
||||
[pirate_ship setCrew:[NSArray arrayWithObject:
|
||||
[OOCharacter randomCharacterWithRole: @"pirate"
|
||||
andOriginalSystem: [UNIVERSE systemSeed]]]];
|
||||
andOriginalSystem: [UNIVERSE systemSeed]]]];
|
||||
}
|
||||
|
||||
// set the owner of the ship to the station so that it can check back for docking later
|
||||
[pirate_ship setOwner:self];
|
||||
@ -1807,7 +1829,7 @@ static NSDictionary* instructions(int station_id, Vector coords, float speed, fl
|
||||
|
||||
[super dumpSelfState];
|
||||
|
||||
switch (alert_level)
|
||||
switch (alertLevel)
|
||||
{
|
||||
case STATION_ALERT_LEVEL_GREEN:
|
||||
alertString = @"green";
|
||||
|
@ -145,8 +145,7 @@ static void DrawWormholeCorona(GLfloat inner_radius, GLfloat outer_radius, int s
|
||||
[UNIVERSE addEntity:ship];
|
||||
|
||||
// Should probably pass the wormhole, but they have no JS representation
|
||||
[ship doScriptEvent:@"shipExitedWormhole"];
|
||||
[[ship getAI] reactToMessage:@"EXITED WITCHSPACE"];
|
||||
[ship doScriptEvent:@"shipExitedWormhole" andReactToAIMessage:@"EXITED WITCHSPACE"];
|
||||
|
||||
// update the ships's position
|
||||
[ship update: time_passed];
|
||||
|
@ -59,7 +59,7 @@ Vector OORandomUnitVector(void)
|
||||
v = make_vector(randf() - 0.5f, randf() - 0.5f, randf() - 0.5f);
|
||||
m = magnitude2(v);
|
||||
}
|
||||
while (m == 0.0f || m > 0.25f); // We're confining to a sphere of radius 0.5 using the sqared magnitude; 0.5 squared is 0.25.
|
||||
while (m > 0.25f || m == 0.0f); // We're confining to a sphere of radius 0.5 using the sqared magnitude; 0.5 squared is 0.25.
|
||||
|
||||
return vector_normal(v);
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ static JSBool PlayerSetProperty(JSContext *context, JSObject *this, jsval name,
|
||||
case kPlayer_score:
|
||||
if (JS_ValueToInt32(context, *value, &iValue))
|
||||
{
|
||||
iValue = (int)OOMax_f(iValue, 0);
|
||||
iValue = MAX(iValue, 0);
|
||||
[player setScore:iValue];
|
||||
}
|
||||
break;
|
||||
|
@ -115,7 +115,8 @@ enum
|
||||
kShip_isThargoid, // is thargoid, boolean, read-only
|
||||
kShip_isTrader, // is trader, boolean, read-only
|
||||
kShip_isPirateVictim, // is pirate victim, boolean, read-only
|
||||
kShip_scriptInfo // arbitrary data for scripts, dictionary, read-only
|
||||
kShip_scriptInfo, // arbitrary data for scripts, dictionary, read-only
|
||||
kShip_trackCloseContacts // generate close contact events, boolean, read/write
|
||||
};
|
||||
|
||||
|
||||
@ -161,6 +162,7 @@ static JSPropertySpec sShipProperties[] =
|
||||
{ "temperature", kShip_temperature, JSPROP_PERMANENT | JSPROP_ENUMERATE },
|
||||
{ "weaponRange", kShip_weaponRange, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
|
||||
{ "withinStationAegis", kShip_withinStationAegis, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
|
||||
{ "trackCloseContacts", kShip_trackCloseContacts, JSPROP_PERMANENT | JSPROP_ENUMERATE },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -390,6 +392,10 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsval name, js
|
||||
result = [entity scriptInfo];
|
||||
if (result == nil) result = [NSDictionary dictionary]; // empty rather than NULL
|
||||
break;
|
||||
|
||||
case kShip_trackCloseContacts:
|
||||
*outValue = BOOLToJSVal([entity trackCloseContacts]);
|
||||
break;
|
||||
|
||||
default:
|
||||
OOReportJavaScriptBadPropertySelector(context, @"Ship", JSVAL_TO_INT(name));
|
||||
@ -516,6 +522,13 @@ static JSBool ShipSetProperty(JSContext *context, JSObject *this, jsval name, js
|
||||
[entity setReportAIMessages:bValue];
|
||||
}
|
||||
break;
|
||||
|
||||
case kShip_trackCloseContacts:
|
||||
if (JS_ValueToBoolean(context, *value, &bValue))
|
||||
{
|
||||
[entity setTrackCloseContacts:bValue];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
OOReportJavaScriptBadPropertySelector(context, @"Ship", JSVAL_TO_INT(name));
|
||||
@ -644,7 +657,7 @@ static JSBool ShipReactToAIMessage(JSContext *context, JSObject *this, uintN arg
|
||||
{
|
||||
if (!thisEnt->isPlayer)
|
||||
{
|
||||
[[thisEnt getAI] reactToMessage:message];
|
||||
[thisEnt reactToAIMessage:message];
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -65,7 +65,8 @@ enum
|
||||
{
|
||||
// Property IDs
|
||||
kStation_isMainStation, // Is [UNIVERSE station], boolean, read-only
|
||||
kStation_hasNPCTraffic
|
||||
kStation_hasNPCTraffic,
|
||||
kStation_alertCondition,
|
||||
};
|
||||
|
||||
|
||||
@ -74,6 +75,7 @@ static JSPropertySpec sStationProperties[] =
|
||||
// JS name ID flags
|
||||
{ "isMainStation", kStation_isMainStation, JSPROP_PERMANENT | JSPROP_ENUMERATE | JSPROP_READONLY },
|
||||
{ "hasNPCTraffic", kStation_hasNPCTraffic, JSPROP_PERMANENT | JSPROP_ENUMERATE },
|
||||
{ "alertCondition", kStation_alertCondition, JSPROP_PERMANENT | JSPROP_ENUMERATE },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
@ -143,6 +145,10 @@ static JSBool StationGetProperty(JSContext *context, JSObject *this, jsval name,
|
||||
*outValue = BOOLToJSVal([entity hasNPCTraffic]);
|
||||
break;
|
||||
|
||||
case kStation_alertCondition:
|
||||
*outValue = INT_TO_JSVAL([entity alertLevel]);
|
||||
break;
|
||||
|
||||
default:
|
||||
OOReportJavaScriptBadPropertySelector(context, @"Station", JSVAL_TO_INT(name));
|
||||
return NO;
|
||||
@ -155,6 +161,8 @@ static JSBool StationSetProperty(JSContext *context, JSObject *this, jsval name,
|
||||
{
|
||||
StationEntity *entity = nil;
|
||||
JSBool bValue;
|
||||
int32 iValue;
|
||||
|
||||
|
||||
if (!JSVAL_IS_INT(name)) return YES;
|
||||
if (!JSStationGetStationEntity(context, this, &entity)) return NO;
|
||||
@ -168,6 +176,13 @@ static JSBool StationSetProperty(JSContext *context, JSObject *this, jsval name,
|
||||
}
|
||||
break;
|
||||
|
||||
case kStation_alertCondition:
|
||||
if (JS_ValueToInt32(context, *value, &iValue))
|
||||
{
|
||||
[entity setAlertLevel:iValue signallingScript:NO]; // Performs range checking
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
OOReportJavaScriptBadPropertySelector(context, @"Station", JSVAL_TO_INT(name));
|
||||
return NO;
|
||||
|
@ -4635,6 +4635,15 @@ static BOOL MaintainLinkedLists(Universe* uni)
|
||||
}
|
||||
|
||||
|
||||
OOINLINE BOOL EntityInRange(Vector p1, Entity *e2, float range)
|
||||
{
|
||||
if (range < 0) return YES;
|
||||
Vector p2 = vector_subtract(e2->position, p1);
|
||||
float cr = range + e2->collision_radius;
|
||||
return magnitude2(p2) < cr * cr;
|
||||
}
|
||||
|
||||
|
||||
// NOTE: OOJSSystem relies on this returning entities in distance-from-player order.
|
||||
// This can be easily changed by removing the [reference isPlayer] conditions in FindJSVisibleEntities().
|
||||
- (NSMutableArray *) findEntitiesMatchingPredicate:(EntityFilterPredicate)predicate
|
||||
@ -4643,8 +4652,7 @@ static BOOL MaintainLinkedLists(Universe* uni)
|
||||
ofEntity:(Entity *)e1
|
||||
{
|
||||
unsigned i;
|
||||
Vector p1, p2;
|
||||
double distance, cr;
|
||||
Vector p1;
|
||||
NSMutableArray *result = nil;
|
||||
|
||||
if (predicate == NULL) predicate = YESPredicate;
|
||||
@ -4657,19 +4665,12 @@ static BOOL MaintainLinkedLists(Universe* uni)
|
||||
for (i = 0; i < n_entities; i++)
|
||||
{
|
||||
Entity *e2 = sortedEntities[i];
|
||||
if (e2 != e1 && predicate(e2, parameter))
|
||||
|
||||
if (e1 != e2 &&
|
||||
EntityInRange(p1, e2, range) &&
|
||||
predicate(e2, parameter))
|
||||
{
|
||||
if (range < 0) distance = -1; // Negative range means infinity
|
||||
else
|
||||
{
|
||||
p2 = vector_subtract(e2->position, p1);
|
||||
cr = range + e2->collision_radius;
|
||||
distance = magnitude2(p2) - cr * cr;
|
||||
}
|
||||
if (distance < 0)
|
||||
{
|
||||
[result addObject:e2];
|
||||
}
|
||||
[result addObject:e2];
|
||||
}
|
||||
}
|
||||
|
||||
|
116
tools/randomVectorIllustration.c
Normal file
116
tools/randomVectorIllustration.c
Normal file
@ -0,0 +1,116 @@
|
||||
// Code to generate http://wiki.alioth.net/index.php/Image:Randomvectordistribution.png
|
||||
|
||||
#import <math.h>
|
||||
#import <stdio.h>
|
||||
|
||||
|
||||
static inline float randf(void)
|
||||
{
|
||||
return ((float)random()) / ((float)0x7FFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
static inline float randcoord(void)
|
||||
{
|
||||
return (randf() * 2.0f) - 1.0f;
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float x, y;
|
||||
} Vector;
|
||||
|
||||
|
||||
static Vector randv(void)
|
||||
{
|
||||
Vector r = { randcoord(), randcoord() };
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
static float magnitude2(Vector v)
|
||||
{
|
||||
return v.x * v.x + v.y * v.y;
|
||||
}
|
||||
|
||||
|
||||
static Vector scalev(Vector v, float s)
|
||||
{
|
||||
v.x *= s;
|
||||
v.y *= s;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
static Vector normal(Vector v)
|
||||
{
|
||||
float m = magnitude2(v);
|
||||
return scalev(v, 1.0f / sqrtf(m));
|
||||
}
|
||||
|
||||
|
||||
static Vector uniformrandomv(void)
|
||||
{
|
||||
Vector v;
|
||||
float m;
|
||||
|
||||
do
|
||||
{
|
||||
v = randv();
|
||||
m = magnitude2(v);
|
||||
}
|
||||
while (m > 1.0f);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
static Vector radialrandomv(void)
|
||||
{
|
||||
Vector v;
|
||||
float m;
|
||||
|
||||
do
|
||||
{
|
||||
v = randv();
|
||||
m = magnitude2(v);
|
||||
}
|
||||
while (m > 1.0f || m == 0.0f);
|
||||
|
||||
return scalev(normal(v), randf());
|
||||
}
|
||||
|
||||
|
||||
#define SIZE 200
|
||||
|
||||
|
||||
static inline unsigned scalecoord(float c)
|
||||
{
|
||||
return (c + 1.0) * ((float)SIZE) * 0.5;
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, const char * argv[])
|
||||
{
|
||||
unsigned char img[SIZE * SIZE] = {0};
|
||||
|
||||
srandomdev();
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < 2500; ++i)
|
||||
{
|
||||
Vector v = uniformrandomv();
|
||||
|
||||
unsigned x = scalecoord(v.x);
|
||||
unsigned y = scalecoord(v.y);
|
||||
|
||||
img[y * SIZE + x] = 0xFF;
|
||||
}
|
||||
|
||||
FILE *f = fopen("/dump.raw", "w");
|
||||
fwrite(img, SIZE, SIZE, f);
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user