Removed entity recycling (and associated bugs) from demo screen code. Work on unifying damage-taking code. World scripts now get notifications of cause of death; set up for similar effect for NPC scripts.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@921 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2007-04-09 17:55:19 +00:00
parent 3aa4cab9c4
commit 7192a86ec6
17 changed files with 672 additions and 586 deletions

View File

@ -57,3 +57,6 @@ OOCargoType StringToCargoType(NSString *string) PURE_FUNC;
NSString *EnergyUnitTypeToString(OOEnergyUnitType unit) CONST_FUNC;
OOEnergyUnitType StringToEnergyUnitType(NSString *string) PURE_FUNC;
NSString *GUIScreenIDToString(OOGUIScreenID screen) CONST_FUNC;
OOEnergyUnitType StringToGUIScreenID(NSString *string) PURE_FUNC;

View File

@ -341,3 +341,60 @@ OOEnergyUnitType StringToEnergyUnitType(NSString *string)
return ENERGY_UNIT_NONE;
}
NSString *GUIScreenIDToString(OOGUIScreenID screen)
{
switch (screen)
{
CASE(GUI_SCREEN_MAIN);
CASE(GUI_SCREEN_INTRO1);
CASE(GUI_SCREEN_INTRO2);
CASE(GUI_SCREEN_STATUS);
CASE(GUI_SCREEN_MANIFEST);
CASE(GUI_SCREEN_EQUIP_SHIP);
CASE(GUI_SCREEN_SHIPYARD);
CASE(GUI_SCREEN_LONG_RANGE_CHART);
CASE(GUI_SCREEN_SHORT_RANGE_CHART);
CASE(GUI_SCREEN_SYSTEM_DATA);
CASE(GUI_SCREEN_MARKET);
CASE(GUI_SCREEN_CONTRACTS);
CASE(GUI_SCREEN_INVENTORY);
CASE(GUI_SCREEN_OPTIONS);
CASE(GUI_SCREEN_LOAD);
CASE(GUI_SCREEN_SAVE);
CASE(GUI_SCREEN_SAVE_OVERWRITE);
CASE(GUI_SCREEN_STICKMAPPER);
CASE(GUI_SCREEN_MISSION);
CASE(GUI_SCREEN_REPORT);
}
return @"UNDEFINED";
}
OOEnergyUnitType StringToGUIScreenID(NSString *string)
{
REVERSE_CASE(GUI_SCREEN_MAIN);
REVERSE_CASE(GUI_SCREEN_INTRO1);
REVERSE_CASE(GUI_SCREEN_INTRO2);
REVERSE_CASE(GUI_SCREEN_STATUS);
REVERSE_CASE(GUI_SCREEN_MANIFEST);
REVERSE_CASE(GUI_SCREEN_EQUIP_SHIP);
REVERSE_CASE(GUI_SCREEN_SHIPYARD);
REVERSE_CASE(GUI_SCREEN_LONG_RANGE_CHART);
REVERSE_CASE(GUI_SCREEN_SHORT_RANGE_CHART);
REVERSE_CASE(GUI_SCREEN_SYSTEM_DATA);
REVERSE_CASE(GUI_SCREEN_MARKET);
REVERSE_CASE(GUI_SCREEN_CONTRACTS);
REVERSE_CASE(GUI_SCREEN_INVENTORY);
REVERSE_CASE(GUI_SCREEN_OPTIONS);
REVERSE_CASE(GUI_SCREEN_LOAD);
REVERSE_CASE(GUI_SCREEN_SAVE);
REVERSE_CASE(GUI_SCREEN_SAVE_OVERWRITE);
REVERSE_CASE(GUI_SCREEN_STICKMAPPER);
REVERSE_CASE(GUI_SCREEN_MISSION);
REVERSE_CASE(GUI_SCREEN_REPORT);
return GUI_SCREEN_MAIN;
}

View File

@ -73,6 +73,31 @@ typedef enum
} OOScanClass;
typedef enum
{
GUI_SCREEN_MAIN,
GUI_SCREEN_INTRO1,
GUI_SCREEN_INTRO2,
GUI_SCREEN_STATUS,
GUI_SCREEN_MANIFEST,
GUI_SCREEN_EQUIP_SHIP,
GUI_SCREEN_SHIPYARD,
GUI_SCREEN_LONG_RANGE_CHART,
GUI_SCREEN_SHORT_RANGE_CHART,
GUI_SCREEN_SYSTEM_DATA,
GUI_SCREEN_MARKET,
GUI_SCREEN_CONTRACTS,
GUI_SCREEN_INVENTORY,
GUI_SCREEN_OPTIONS,
GUI_SCREEN_LOAD,
GUI_SCREEN_SAVE,
GUI_SCREEN_SAVE_OVERWRITE,
GUI_SCREEN_STICKMAPPER,
GUI_SCREEN_MISSION,
GUI_SCREEN_REPORT
} OOGUIScreenID;
typedef enum
{
INSTINCT_NULL = 0U,

View File

@ -39,32 +39,6 @@ MA 02110-1301, USA.
#define SCRIPT_TIMER_INTERVAL 10.0
// Shouldn't this be in GuiDisplayGen.h? -- Ahruman
typedef enum
{
GUI_SCREEN_MAIN,
GUI_SCREEN_INTRO1,
GUI_SCREEN_INTRO2,
GUI_SCREEN_STATUS,
GUI_SCREEN_MANIFEST,
GUI_SCREEN_EQUIP_SHIP,
GUI_SCREEN_SHIPYARD,
GUI_SCREEN_LONG_RANGE_CHART,
GUI_SCREEN_SHORT_RANGE_CHART,
GUI_SCREEN_SYSTEM_DATA,
GUI_SCREEN_MARKET,
GUI_SCREEN_CONTRACTS,
GUI_SCREEN_INVENTORY,
GUI_SCREEN_OPTIONS,
GUI_SCREEN_LOAD,
GUI_SCREEN_SAVE,
GUI_SCREEN_SAVE_OVERWRITE,
GUI_SCREEN_STICKMAPPER,
GUI_SCREEN_MISSION,
GUI_SCREEN_REPORT,
} OOGUIScreen;
enum
{
GUI_ROW_OPTIONS_QUICKSAVE = 6,
@ -530,7 +504,6 @@ typedef enum
+ (id)sharedPlayer;
- (void) init_keys;
- (void) warnAboutHostiles;
- (void) unloadCargoPods;
@ -631,7 +604,6 @@ typedef enum
- (void) takeInternalDamage;
- (NSDictionary*) damageInformation;
- (void) getDestroyed;
- (void) loseTargetStatus;
@ -723,7 +695,7 @@ typedef enum
- (void) sendMessageToScripts:(NSString *)message;
- (void) sendMessageToScripts:(NSString *)message withString:(NSString *)argument;
- (void) sendMessageToScripts:(NSString *)message withInteger:(int)argument;
- (void) sendMessageToScripts:(NSString *)message withArguments:(NSArray *)arguments;
- (BOOL)showInfoFlag;

View File

@ -82,105 +82,6 @@ static PlayerEntity *sSharedPlayer = nil;
}
- (void) init_keys
{
NSMutableDictionary *kdic = [NSMutableDictionary dictionaryWithDictionary:[ResourceManager dictionaryFromFilesNamed:@"keyconfig.plist" inFolder:@"Config" andMerge:YES]];
// pre-process kdic - replace any strings with an integer representing the ASCII value of the first character
int i;
NSArray* keys = [kdic allKeys];
for (i = 0; i < [keys count]; i++)
{
id key = [keys objectAtIndex:i];
id value = [kdic objectForKey: key];
int i_value = [value intValue];
// for '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' - we want to interpret those as strings - not numbers
// alphabetical characters and symbols will return an intValue of 0
// acceptable i_values are 11 .. 255
if ([value isKindOfClass:[NSString class]] && (i_value < 10))
{
char keychar = 0;
NSString* keystring = (NSString*)value;
if ([keystring length])
keychar = [keystring characterAtIndex: 0] & 0x00ff; // uses lower byte of unichar
[kdic setObject:[NSNumber numberWithInt:(int)keychar] forKey:key];
}
}
// set default keys...
#define LOAD_KEY_SETTING(name, default) name = [kdic intForKey:@#name defaultValue:default]
LOAD_KEY_SETTING(key_roll_left, gvArrowKeyLeft );
LOAD_KEY_SETTING(key_roll_right, gvArrowKeyRight );
LOAD_KEY_SETTING(key_pitch_forward, gvArrowKeyUp );
LOAD_KEY_SETTING(key_pitch_back, gvArrowKeyDown );
LOAD_KEY_SETTING(key_yaw_left, ',' );
LOAD_KEY_SETTING(key_yaw_right, '.' );
LOAD_KEY_SETTING(key_increase_speed, 'w' );
LOAD_KEY_SETTING(key_decrease_speed, 's' );
LOAD_KEY_SETTING(key_inject_fuel, 'i' );
LOAD_KEY_SETTING(key_fire_lasers, 'a' );
LOAD_KEY_SETTING(key_launch_missile, 'm' );
LOAD_KEY_SETTING(key_next_missile, 'y' );
LOAD_KEY_SETTING(key_ecm, 'e' );
LOAD_KEY_SETTING(key_target_missile, 't' );
LOAD_KEY_SETTING(key_untarget_missile, 'u' );
LOAD_KEY_SETTING(key_ident_system, 'r' );
LOAD_KEY_SETTING(key_scanner_zoom, 'z' );
LOAD_KEY_SETTING(key_scanner_unzoom, 'Z' );
LOAD_KEY_SETTING(key_launch_escapepod, 27 /* esc */ );
LOAD_KEY_SETTING(key_energy_bomb, '\t' );
LOAD_KEY_SETTING(key_galactic_hyperspace, 'g' );
LOAD_KEY_SETTING(key_hyperspace, 'h' );
LOAD_KEY_SETTING(key_jumpdrive, 'j' );
LOAD_KEY_SETTING(key_dump_cargo, 'd' );
LOAD_KEY_SETTING(key_rotate_cargo, 'R' );
LOAD_KEY_SETTING(key_autopilot, 'c' );
LOAD_KEY_SETTING(key_autopilot_target, 'C' );
LOAD_KEY_SETTING(key_autodock, 'D' );
LOAD_KEY_SETTING(key_snapshot, '*' );
LOAD_KEY_SETTING(key_docking_music, 's' );
LOAD_KEY_SETTING(kay_advanced_nav_array, '!' );
LOAD_KEY_SETTING(key_map_home, gvHomeKey );
LOAD_KEY_SETTING(key_map_info, 'i' );
LOAD_KEY_SETTING(key_pausebutton, 'p' );
LOAD_KEY_SETTING(key_show_fps, 'F' );
LOAD_KEY_SETTING(key_mouse_control, 'M' );
LOAD_KEY_SETTING(key_comms_log, '`' );
LOAD_KEY_SETTING(key_next_compass_mode, '\\' );
LOAD_KEY_SETTING(key_cloaking_device, '0' );
LOAD_KEY_SETTING(key_contract_info, '\?' );
LOAD_KEY_SETTING(key_next_target, '+' );
LOAD_KEY_SETTING(key_previous_target, '-' );
LOAD_KEY_SETTING(key_custom_view, 'v' );
LOAD_KEY_SETTING(key_dump_target_state, NUM_KEYS + 1 ); // Default to no assignment.
// other keys are SET and cannot be varied
// Enable polling
pollControls=YES;
}
- (void) unloadCargoPods
{
/* loads commodities from the cargo pods onto the ship's manifest */
@ -882,7 +783,7 @@ static PlayerEntity *sSharedPlayer = nil;
script = [[ResourceManager loadScripts] retain];
[self init_keys];
[self initControls];
return self;
}
@ -1588,8 +1489,7 @@ double scoopSoundPlayTime = 0.0;
OOTrumble* trum = trumbles[i - 1];
[trum updateTrumble:delta_t];
}
// if ((status == STATUS_COCKPIT_DISPLAY)&&(gui_screen != GUI_SCREEN_INTRO1)&&(gui_screen != GUI_SCREEN_INTRO2)&&(gui_screen != GUI_SCREEN_MISSION)&&(gui_screen != GUI_SCREEN_SHIPYARD))
if ((status == STATUS_START_GAME)&&(gui_screen != GUI_SCREEN_INTRO1)&&(gui_screen != GUI_SCREEN_INTRO2))
[self setGuiToIntro1Screen]; //set up demo mode
@ -1603,8 +1503,6 @@ double scoopSoundPlayTime = 0.0;
if (!docked_station)
{
// do flight routines
//// velocity stuff
position.x += delta_t * velocity.x;
@ -3211,7 +3109,8 @@ double scoopSoundPlayTime = 0.0;
[[hunter getAI] message:@"TARGET_DESTROYED"];
}
}
[self getDestroyed];
[self getDestroyedBy:other context:@"energy damage"];
}
if (internal_damage) [self takeInternalDamage];
@ -3287,7 +3186,8 @@ double scoopSoundPlayTime = 0.0;
[[hunter getAI] message:@"TARGET_DESTROYED"];
}
}
[self getDestroyed];
[self getDestroyedBy:ent context:@"scrape damage"];
}
if (internal_damage) [self takeInternalDamage];
@ -3337,7 +3237,9 @@ double scoopSoundPlayTime = 0.0;
// oops we're burning up!
if (energy <= 0.0)
[self getDestroyed];
{
[self getDestroyedBy:nil context:@"heat damage"];
}
else
{
// warn if I'm low on energy
@ -3612,13 +3514,13 @@ double scoopSoundPlayTime = 0.0;
return nil;
}
- (void) getDestroyed
- (void) getDestroyedBy:(Entity *)whom context:(NSString *)why
{
NSString* scoreMS = [NSString stringWithFormat:@"Score: %.1f Credits",credits/10.0];
if (![[UNIVERSE gameController] playerFileToLoad])
[[UNIVERSE gameController] setPlayerFileToLoad: save_path]; // make sure we load the correct game
energy = 0.0;
afterburner_engaged = NO;
[UNIVERSE setDisplayText:NO];
@ -3638,8 +3540,9 @@ double scoopSoundPlayTime = 0.0;
[UNIVERSE displayMessage:@"" forCount:30.0];
[UNIVERSE displayMessage:@"Press Space" forCount:30.0];
shot_time = 0.0;
[self sendMessageToScripts:@"didBecomeDead"];
if (whom == nil) whom = (id)[NSNull null];
[self sendMessageToScripts:@"didBecomeDead" withArguments:[NSArray arrayWithObjects:whom, why, nil]];
[self loseTargetStatus];
}
@ -6514,36 +6417,27 @@ OOSound* burnersound;
- (void) sendMessageToScripts:(NSString *)message
{
NSEnumerator *scriptEnum;
OOScript *theScript;
for (scriptEnum = [script objectEnumerator]; (theScript = [scriptEnum nextObject]); )
{
[theScript doEvent:message];
}
[self sendMessageToScripts:message withArguments:nil];
}
- (void) sendMessageToScripts:(NSString *)message withString:(NSString *)argument
{
NSEnumerator *scriptEnum;
OOScript *theScript;
NSArray *arguments = nil;
for (scriptEnum = [script objectEnumerator]; (theScript = [scriptEnum nextObject]); )
{
[theScript doEvent:message withStringArgument:argument];
}
if (argument != nil) arguments = [NSArray arrayWithObject:argument];
[self sendMessageToScripts:message withArguments:arguments];
}
- (void) sendMessageToScripts:(NSString *)message withInteger:(int)argument
- (void) sendMessageToScripts:(NSString *)message withArguments:(NSArray *)arguments
{
NSEnumerator *scriptEnum;
OOScript *theScript;
for (scriptEnum = [script objectEnumerator]; (theScript = [scriptEnum nextObject]); )
{
[theScript doEvent:message withIntegerArgument:argument];
[theScript doEvent:message withArguments:arguments];
}
}

View File

@ -29,6 +29,8 @@ MA 02110-1301, USA.
@interface PlayerEntity (Controls)
- (void) initControls;
- (void) pollControls:(double) delta_t;
- (void) pollApplicationControls;
- (void) pollFlightControls:(double) delta_t;

View File

@ -37,10 +37,12 @@ MA 02110-1301, USA.
#import "MyOpenGLView.h"
#import "OOSound.h"
#import "OOStringParsing.h"
#import "OOCollectionExtractors.h"
#import "ResourceManager.h"
#import "JoystickHandler.h"
#ifndef GNUSTEP
#if OOLITE_MAC_OS_X
#import "Groolite.h"
#endif
@ -50,6 +52,106 @@ static NSString * const kOOLogFlightTrainingBeacons = @"beacon.list.flightTrain
@implementation PlayerEntity (Controls)
- (void) initControls
{
NSMutableDictionary *kdic = [NSMutableDictionary dictionaryWithDictionary:[ResourceManager dictionaryFromFilesNamed:@"keyconfig.plist" inFolder:@"Config" andMerge:YES]];
// pre-process kdic - replace any strings with an integer representing the ASCII value of the first character
int i;
NSArray* keys = [kdic allKeys];
for (i = 0; i < [keys count]; i++)
{
id key = [keys objectAtIndex:i];
id value = [kdic objectForKey: key];
int i_value = [value intValue];
// for '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' - we want to interpret those as strings - not numbers
// alphabetical characters and symbols will return an intValue of 0
// acceptable i_values are 11 .. 255
if ([value isKindOfClass:[NSString class]] && (i_value < 10))
{
char keychar = 0;
NSString* keystring = (NSString*)value;
if ([keystring length])
keychar = [keystring characterAtIndex: 0] & 0x00ff; // uses lower byte of unichar
[kdic setObject:[NSNumber numberWithInt:(int)keychar] forKey:key];
}
}
// set default keys...
#define LOAD_KEY_SETTING(name, default) name = [kdic intForKey:@#name defaultValue:default]
LOAD_KEY_SETTING(key_roll_left, gvArrowKeyLeft );
LOAD_KEY_SETTING(key_roll_right, gvArrowKeyRight );
LOAD_KEY_SETTING(key_pitch_forward, gvArrowKeyUp );
LOAD_KEY_SETTING(key_pitch_back, gvArrowKeyDown );
LOAD_KEY_SETTING(key_yaw_left, ',' );
LOAD_KEY_SETTING(key_yaw_right, '.' );
LOAD_KEY_SETTING(key_increase_speed, 'w' );
LOAD_KEY_SETTING(key_decrease_speed, 's' );
LOAD_KEY_SETTING(key_inject_fuel, 'i' );
LOAD_KEY_SETTING(key_fire_lasers, 'a' );
LOAD_KEY_SETTING(key_launch_missile, 'm' );
LOAD_KEY_SETTING(key_next_missile, 'y' );
LOAD_KEY_SETTING(key_ecm, 'e' );
LOAD_KEY_SETTING(key_target_missile, 't' );
LOAD_KEY_SETTING(key_untarget_missile, 'u' );
LOAD_KEY_SETTING(key_ident_system, 'r' );
LOAD_KEY_SETTING(key_scanner_zoom, 'z' );
LOAD_KEY_SETTING(key_scanner_unzoom, 'Z' );
LOAD_KEY_SETTING(key_launch_escapepod, 27 /* esc */ );
LOAD_KEY_SETTING(key_energy_bomb, '\t' );
LOAD_KEY_SETTING(key_galactic_hyperspace, 'g' );
LOAD_KEY_SETTING(key_hyperspace, 'h' );
LOAD_KEY_SETTING(key_jumpdrive, 'j' );
LOAD_KEY_SETTING(key_dump_cargo, 'd' );
LOAD_KEY_SETTING(key_rotate_cargo, 'R' );
LOAD_KEY_SETTING(key_autopilot, 'c' );
LOAD_KEY_SETTING(key_autopilot_target, 'C' );
LOAD_KEY_SETTING(key_autodock, 'D' );
LOAD_KEY_SETTING(key_snapshot, '*' );
LOAD_KEY_SETTING(key_docking_music, 's' );
LOAD_KEY_SETTING(kay_advanced_nav_array, '!' );
LOAD_KEY_SETTING(key_map_home, gvHomeKey );
LOAD_KEY_SETTING(key_map_info, 'i' );
LOAD_KEY_SETTING(key_pausebutton, 'p' );
LOAD_KEY_SETTING(key_show_fps, 'F' );
LOAD_KEY_SETTING(key_mouse_control, 'M' );
LOAD_KEY_SETTING(key_comms_log, '`' );
LOAD_KEY_SETTING(key_next_compass_mode, '\\' );
LOAD_KEY_SETTING(key_cloaking_device, '0' );
LOAD_KEY_SETTING(key_contract_info, '\?' );
LOAD_KEY_SETTING(key_next_target, '+' );
LOAD_KEY_SETTING(key_previous_target, '-' );
LOAD_KEY_SETTING(key_custom_view, 'v' );
LOAD_KEY_SETTING(key_dump_target_state, NUM_KEYS + 1 ); // Default to no assignment.
// other keys are SET and cannot be varied
// Enable polling
pollControls=YES;
}
- (void) pollControls:(double) delta_t
{
MyOpenGLView *gameView = (MyOpenGLView *)[UNIVERSE gameView];

View File

@ -599,70 +599,55 @@ static NSString * mission_key;
- (NSString *) gui_screen_string
{
switch(gui_screen)
{
case GUI_SCREEN_EQUIP_SHIP :
return @"GUI_SCREEN_EQUIP_SHIP";
case GUI_SCREEN_INTRO1 :
return @"GUI_SCREEN_INTRO1";
case GUI_SCREEN_INTRO2 :
return @"GUI_SCREEN_INTRO2";
case GUI_SCREEN_INVENTORY :
return @"GUI_SCREEN_INVENTORY";
case GUI_SCREEN_LONG_RANGE_CHART :
return @"GUI_SCREEN_LONG_RANGE_CHART";
case GUI_SCREEN_MAIN :
return @"GUI_SCREEN_MAIN";
case GUI_SCREEN_MARKET :
return @"GUI_SCREEN_MARKET";
case GUI_SCREEN_MISSION :
return @"GUI_SCREEN_MISSION";
case GUI_SCREEN_OPTIONS :
return @"GUI_SCREEN_OPTIONS";
case GUI_SCREEN_SHORT_RANGE_CHART :
return @"GUI_SCREEN_SHORT_RANGE_CHART";
case GUI_SCREEN_STATUS :
return @"GUI_SCREEN_STATUS";
case GUI_SCREEN_SYSTEM_DATA :
return @"GUI_SCREEN_SYSTEM_DATA";
default :
return @"UNDEFINED";
}
return GUIScreenIDToString(gui_screen);
}
- (NSNumber *) galaxy_number
{
return [NSNumber numberWithInt:galaxy_number];
}
- (NSNumber *) planet_number
{
if (![UNIVERSE sun])
return [NSNumber numberWithInt:-1];
return [NSNumber numberWithInt:[UNIVERSE findSystemNumberAtCoords:galaxy_coordinates withGalaxySeed:galaxy_seed]];
}
- (NSNumber *) score_number
{
return [NSNumber numberWithInt:ship_kills];
}
- (NSNumber *) credits_number
{
return [NSNumber numberWithFloat: 0.1 * credits];
}
- (NSNumber *) scriptTimer_number
{
return [NSNumber numberWithDouble:script_time];
}
static int shipsFound;
- (NSNumber *) shipsFound_number
{
return [NSNumber numberWithInt:shipsFound];
}
- (NSNumber *) legalStatus_number
{
return [NSNumber numberWithInt:legal_status];
}
static int scriptRandomSeed = -1; // ensure proper random function
- (NSNumber *) d100_number
{
@ -673,6 +658,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
return [NSNumber numberWithInt:d100];
}
- (NSNumber *) pseudoFixedD100_number
{
// set the system seed for random number generation
@ -681,6 +667,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
return [NSNumber numberWithInt:d100];
}
- (NSNumber *) d256_number
{
if (scriptRandomSeed == -1) scriptRandomSeed = floor(1301 * ship_clock); // stop predictable sequences
@ -690,6 +677,7 @@ static int scriptRandomSeed = -1; // ensure proper random function
return [NSNumber numberWithInt:d256];
}
- (NSNumber *) pseudoFixedD256_number
{
// set the system seed for random number generation
@ -698,31 +686,37 @@ static int scriptRandomSeed = -1; // ensure proper random function
return [NSNumber numberWithInt:d256];
}
- (NSNumber *) clock_number // returns the game time in seconds
{
return [NSNumber numberWithDouble:ship_clock];
}
- (NSNumber *) clock_secs_number // returns the game time in seconds
{
return [NSNumber numberWithInt:floor(ship_clock)];
}
- (NSNumber *) clock_mins_number // returns the game time in minutes
{
return [NSNumber numberWithInt:floor(ship_clock / 60.0)];
}
- (NSNumber *) clock_hours_number // returns the game time in hours
{
return [NSNumber numberWithInt:floor(ship_clock / 3600.0)];
}
- (NSNumber *) clock_days_number // returns the game time in days
{
return [NSNumber numberWithInt:floor(ship_clock / 86400.0)];
}
- (NSNumber *) fuel_level_number // returns the fuel level in LY
{
return [NSNumber numberWithFloat:floor(0.1 * fuel)];
@ -737,11 +731,13 @@ static int scriptRandomSeed = -1; // ensure proper random function
return @"NO";
}
- (NSString *) foundEquipment_bool
{
return (found_equipment)? @"YES" : @"NO";
}
- (NSString *) sunWillGoNova_bool // returns whether the sun is going to go nova
{
return ([[UNIVERSE sun] willGoNova])? @"YES" : @"NO";

View File

@ -28,6 +28,7 @@ MA 02110-1301, USA.
#import "Entity.h"
#import "OOJavaScriptEngine.h"
#import "NSStringOOExtensions.h"
#import "EntityOOJavaScriptExtensions.h"
OOJSScript *currentOOJSScript;
@ -163,64 +164,29 @@ JSClass script_class =
- (void)runWithTarget:(Entity *)target
{
[self doEvent:@"tickle" withStringArgument:[[PlayerEntity sharedPlayer] status_string]];
[self doEvent:@"tickle" withArguments:[NSArray arrayWithObject:[[PlayerEntity sharedPlayer] status_string]]];
}
- (BOOL) doEvent: (NSString *) eventName
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)arguments
{
jsval rval;
JSBool ok;
BOOL OK;
jsval value;
JSFunction *function;
uintN argc;
jsval *argv = NULL;
ok = JS_GetProperty(context, object, [eventName cString], &rval);
if (ok && !JSVAL_IS_VOID(rval)) {
JSFunction *func = JS_ValueToFunction(context, rval);
if (func != 0x00) {
OK = JS_GetProperty(context, object, [eventName cString], &value);
if (OK && !JSVAL_IS_VOID(value))
{
function = JS_ValueToFunction(context, value);
if (function != NULL)
{
currentOOJSScript = self;
ok = JS_CallFunction(context, object, func, 0, 0x00, &rval);
if (ok)
return YES;
}
}
return NO;
}
- (BOOL) doEvent: (NSString *) eventName withIntegerArgument:(int)argument
{
jsval rval;
JSBool ok;
ok = JS_GetProperty(context, object, [eventName cString], &rval);
if (ok && !JSVAL_IS_VOID(rval)) {
JSFunction *func = JS_ValueToFunction(context, rval);
if (func != 0x00) {
currentOOJSScript = self;
jsval args[1];
args[0] = INT_TO_JSVAL(argument);
ok = JS_CallFunction(context, object, func, 1, args, &rval);
if (ok)
return YES;
}
}
return NO;
}
- (BOOL) doEvent: (NSString *) eventName withStringArgument:(NSString *)argument
{
jsval rval;
JSBool ok;
ok = JS_GetProperty(context, object, [eventName cString], &rval);
if (ok && !JSVAL_IS_VOID(rval)) {
JSFunction *func = JS_ValueToFunction(context, rval);
if (func != 0x00) {
currentOOJSScript = self;
jsval args[1];
args[0] = [argument javaScriptValueInContext:context];
ok = JS_CallFunction(context, object, func, 1, args, &rval);
if (ok)
return YES;
JSArgumentsFromArray(context, arguments, &argc, &argv);
OK = JS_CallFunction(context, object, function, argc, argv, &value);
if (argv != NULL) free(argv);
return OK;
}
}

View File

@ -49,7 +49,7 @@ void OOReportJavaScriptErrorWithArguments(JSContext *context, NSString *format,
void OOReportJavaScriptWarning(JSContext *context, NSString *format, ...);
void OOReportJavaScriptWarningWithArguments(JSContext *context, NSString *format, va_list args);
/* QuaternionFromArgumentList()
/* NumberFromArgumentList()
Get a single number from an argument list. The optional outConsumed
argument can be used to find out how many parameters were used (currently,
@ -62,6 +62,18 @@ void OOReportJavaScriptWarningWithArguments(JSContext *context, NSString *format
BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString *function, uintN argc, jsval *argv, double *outNumber, uintN *outConsumed);
/* JSArgumentsFromArray()
Convert an ObjC array to an array of JavaScript values. For objects which
don't respond to -javaScriptValueInContext:, JSVAL_VOID will be used.
*outArgv will be NULL if *outArgc is 0. If *outArgv is not NULL, it should
be free()d when finished with.
*/
BOOL JSArgumentsFromArray(JSContext *context, NSArray *array, uintN *outArgc, jsval **outArgv);
@protocol OOJavaScriptConversion <NSObject>
- (jsval)javaScriptValueInContext:(JSContext *)context;
@ -91,4 +103,9 @@ BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString
@end
@interface NSNull (OOJavaScriptExtensions) <OOJavaScriptConversion>
@end
NSString *JSPropertyAsString(JSContext *context, JSObject *object, const char *name);

View File

@ -1378,6 +1378,57 @@ BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString
}
BOOL JSArgumentsFromArray(JSContext *context, NSArray *array, uintN *outArgc, jsval **outArgv)
{
if (outArgc != NULL) *outArgc = 0;
if (outArgv != NULL) *outArgv = NULL;
if (array == nil) return YES;
// Sanity checks.
if (outArgc == NULL || outArgv == NULL)
{
OOLogGenericParameterError();
return NO;
}
if (context == NULL) context = [[OOJavaScriptEngine sharedEngine] context];
uintN i = 0, argc = [array count];
NSEnumerator *objectEnum = nil;
id object = nil;
jsval *argv = NULL;
if (argc == 0) return YES;
// Allocate result buffer
argv = malloc(sizeof *argv * argc);
if (argv == NULL)
{
OOLog(kOOLogAllocationFailure, @"Failed to allocate space for %u JavaScript parameters.", argc);
return NO;
}
// Convert objects
for (objectEnum = [array objectEnumerator]; (object = [objectEnum nextObject]); )
{
argv[i] = JSVAL_VOID;
NS_DURING
if ([object respondsToSelector:@selector(javaScriptValueInContext:)])
{
argv[i] = [object javaScriptValueInContext:context];
}
NS_HANDLER
NS_ENDHANDLER
++i;
}
*outArgc = argc;
*outArgv = argv;
return YES;
}
@implementation NSString (OOJavaScriptExtensions)
// Convert a JSString to an NSString.
@ -1529,6 +1580,16 @@ BOOL NumberFromArgumentList(JSContext *context, NSString *scriptClass, NSString
@end
@implementation NSNull (OOJavaScriptExtensions)
- (jsval)javaScriptValueInContext:(JSContext *)context
{
return JSVAL_NULL;
}
@end
NSString *JSPropertyAsString(JSContext *context, JSObject *object, const char *name)
{
JSBool OK;

View File

@ -105,21 +105,7 @@ static NSString * const kKeyMetadata = @"!metadata!";
}
- (BOOL)doEvent:(NSString *)eventName
{
// PList scripts don't have event handlers.
return NO;
}
- (BOOL)doEvent:(NSString *)eventName withIntegerArgument:(int)argument
{
// PList scripts don't have event handlers.
return NO;
}
- (BOOL)doEvent:(NSString *)eventName withStringArgument:(NSString *)argument
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)argument
{
// PList scripts don't have event handlers.
return NO;

View File

@ -61,7 +61,6 @@ MA 02110-1301, USA.
- (void)runWithTarget:(Entity *)target;
- (BOOL)doEvent:(NSString *)eventName;
- (BOOL)doEvent:(NSString *)eventName withIntegerArgument:(int)argument;
- (BOOL)doEvent:(NSString *)eventName withStringArgument:(NSString *)argument;
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)argument;
@end

View File

@ -257,19 +257,11 @@ static NSString * const kOOLogLoadScriptNone = @"script.load.none";
- (BOOL)doEvent:(NSString *)eventName
{
OOLog(kOOLogScriptSubclassResponsibility, @"OOScript should not be used directly!");
return NO;
return [self doEvent:eventName withArguments:nil];
}
- (BOOL)doEvent:(NSString *)eventName withIntegerArgument:(int)argument
{
OOLog(kOOLogScriptSubclassResponsibility, @"OOScript should not be used directly!");
return NO;
}
- (BOOL)doEvent:(NSString *)eventName withStringArgument:(NSString *)argument
- (BOOL)doEvent:(NSString *)eventName withArguments:(NSArray *)arguments
{
OOLog(kOOLogScriptSubclassResponsibility, @"OOScript should not be used directly!");
return NO;

View File

@ -162,7 +162,8 @@ MA 02110-1301, USA.
isNearPlanetSurface: 1,
isFrangible: 1, // frangible => subentities can be damaged individually
cloaking_device_active: 1, // cloaking_device
canFragment: 1; // Can it break into wreckage?
canFragment: 1, // Can it break into wreckage?
suppressExplosion: 1; // Avoid exploding on death (script hook)
int fuel; // witch-space fuel
GLfloat fuel_accumulator;
@ -433,7 +434,7 @@ MA 02110-1301, USA.
- (void) setRoll:(double) amount;
- (void) setPitch:(double) amount;
- (void) setThrust:(double) amount;
- (void)setThrustForDemo:(float)factor;
- (void) setBounty:(OOCreditsQuantity) amount;
- (OOCreditsQuantity) getBounty;
@ -477,6 +478,7 @@ MA 02110-1301, USA.
- (void) dealEnergyDamageWithinDesiredRange;
- (void) dealMomentumWithinDesiredRange:(double)amount;
- (void) getDestroyedBy:(Entity *)whom context:(NSString *)why;
- (void) becomeExplosion;
- (void) becomeLargeExplosion:(double) factor;
- (void) becomeEnergyBlast;
@ -507,6 +509,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other);
- (GLfloat)laserHeatLevel;
- (GLfloat)hullHeatLevel;
- (void)setSuppressExplosion:(BOOL)suppress;
/*-----------------------------------------

View File

@ -3647,9 +3647,9 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
}
- (void) setThrust:(double) amount
- (void)setThrustForDemo:(float)factor
{
thrust = amount;
flight_speed = factor * max_flight_speed;
}
@ -3897,6 +3897,15 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
return is_hulk;
}
- (void) getDestroyedBy:(Entity *)whom context:(NSString *)context
{
suppressExplosion = NO; // Can only be set in death handler
// TODO: send didBecomeDead(whom, context) script event here
[self becomeExplosion];
}
- (void) becomeExplosion
{
OOCargoQuantity cargo_to_go;
@ -3943,285 +3952,287 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
[death_actions release];
death_actions = nil;
}
if ([roles isEqual:@"thargoid"])
[self broadcastThargoidDestroyed];
if ((mass > 200000.0f)&&(randf() < 0.25f)) // big!
{
// draw an expanding ring
ParticleEntity *ring = [[ParticleEntity alloc] initHyperringFromShip:self]; // retained
Vector ring_vel = [self velocity];
ring_vel.x *= 0.25; ring_vel.y *= 0.25; ring_vel.z *= 0.25; // quarter velocity
[ring setVelocity:ring_vel];
[UNIVERSE addEntity:ring];
[ring release];
}
// several parts to the explosion:
// 1. fast sparks
fragment = [[ParticleEntity alloc] initFragburstSize:collision_radius FromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
// 2. slow clouds
fragment = [[ParticleEntity alloc] initBurst2Size:collision_radius FromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
// 3. flash
fragment = [[ParticleEntity alloc] initFlashSize:collision_radius FromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
BOOL add_more_explosion = YES;
if (UNIVERSE)
if (!suppressExplosion)
{
add_more_explosion &= (UNIVERSE->n_entities < 0.95 * UNIVERSE_MAX_ENTITIES); //
add_more_explosion &= ([UNIVERSE getTimeDelta] < 0.125); // FPS > 8
}
// quick - check if UNIVERSE is nearing limit for entities - if it is don't add to it!
//
if (add_more_explosion)
{
// we need to throw out cargo at this point.
NSArray *jetsam = nil; // this will contain the stuff to get thrown out
int cargo_chance = 10;
if ([[name lowercaseString] rangeOfString:@"medical"].location != NSNotFound)
if ((mass > 200000.0f)&&(randf() < 0.25f)) // big!
{
// draw an expanding ring
ParticleEntity *ring = [[ParticleEntity alloc] initHyperringFromShip:self]; // retained
Vector ring_vel = [self velocity];
ring_vel.x *= 0.25; ring_vel.y *= 0.25; ring_vel.z *= 0.25; // quarter velocity
[ring setVelocity:ring_vel];
[UNIVERSE addEntity:ring];
[ring release];
}
// several parts to the explosion:
// 1. fast sparks
fragment = [[ParticleEntity alloc] initFragburstSize:collision_radius FromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
// 2. slow clouds
fragment = [[ParticleEntity alloc] initBurst2Size:collision_radius FromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
// 3. flash
fragment = [[ParticleEntity alloc] initFlashSize:collision_radius FromPosition:xposition];
[UNIVERSE addEntity:fragment];
[fragment release];
BOOL add_more_explosion = YES;
if (UNIVERSE)
{
add_more_explosion &= (UNIVERSE->n_entities < 0.95 * UNIVERSE_MAX_ENTITIES); //
add_more_explosion &= ([UNIVERSE getTimeDelta] < 0.125); // FPS > 8
}
// quick - check if UNIVERSE is nearing limit for entities - if it is don't add to it!
//
if (add_more_explosion)
{
// we need to throw out cargo at this point.
NSArray *jetsam = nil; // this will contain the stuff to get thrown out
int cargo_chance = 10;
if ([[name lowercaseString] rangeOfString:@"medical"].location != NSNotFound)
{
cargo_to_go = max_cargo * cargo_chance / 100;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
[self setCargo:[UNIVERSE getContainersOfDrugs:cargo_to_go]];
cargo_chance = 100; // chance of any given piece of cargo surviving decompression
cargo_flag = CARGO_FLAG_CANISTERS;
}
cargo_to_go = max_cargo * cargo_chance / 100;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
[self setCargo:[UNIVERSE getContainersOfDrugs:cargo_to_go]];
cargo_chance = 100; // chance of any given piece of cargo surviving decompression
cargo_flag = CARGO_FLAG_CANISTERS;
}
cargo_to_go = max_cargo * cargo_chance / 100;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
cargo_chance = 100; // chance of any given piece of cargo surviving decompression
switch (cargo_flag)
{
case CARGO_FLAG_NONE:
case CARGO_FLAG_FULL_PASSENGERS:
break;
case CARGO_FLAG_FULL_UNIFORM :
{
NSString* commodity_name = (NSString*)[shipinfoDictionary objectForKey:@"cargo_carried"];
jetsam = [UNIVERSE getContainersOfCommodity:commodity_name :cargo_to_go];
}
break;
case CARGO_FLAG_FULL_PLENTIFUL :
jetsam = [UNIVERSE getContainersOfPlentifulGoods:cargo_to_go];
break;
case CARGO_FLAG_PIRATE :
cargo_to_go = likely_cargo;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
cargo_chance = 65; // 35% chance of spoilage
jetsam = [UNIVERSE getContainersOfScarceGoods:cargo_to_go];
break;
case CARGO_FLAG_FULL_SCARCE :
jetsam = [UNIVERSE getContainersOfScarceGoods:cargo_to_go];
break;
case CARGO_FLAG_CANISTERS:
jetsam = [NSArray arrayWithArray:cargo]; // what the ship is carrying
[cargo removeAllObjects]; // dispense with it!
break;
}
// Throw out cargo
//
if (jetsam)
{
int n_jetsam = [jetsam count];
//
for (i = 0; i < n_jetsam; i++)
switch (cargo_flag)
{
if (ranrot_rand() % 100 < cargo_chance) // chance of any given piece of cargo surviving decompression
case CARGO_FLAG_NONE:
case CARGO_FLAG_FULL_PASSENGERS:
break;
case CARGO_FLAG_FULL_UNIFORM :
{
NSString* commodity_name = (NSString*)[shipinfoDictionary objectForKey:@"cargo_carried"];
jetsam = [UNIVERSE getContainersOfCommodity:commodity_name :cargo_to_go];
}
break;
case CARGO_FLAG_FULL_PLENTIFUL :
jetsam = [UNIVERSE getContainersOfPlentifulGoods:cargo_to_go];
break;
case CARGO_FLAG_PIRATE :
cargo_to_go = likely_cargo;
while (cargo_to_go > 15)
cargo_to_go = ranrot_rand() % cargo_to_go;
cargo_chance = 65; // 35% chance of spoilage
jetsam = [UNIVERSE getContainersOfScarceGoods:cargo_to_go];
break;
case CARGO_FLAG_FULL_SCARCE :
jetsam = [UNIVERSE getContainersOfScarceGoods:cargo_to_go];
break;
case CARGO_FLAG_CANISTERS:
jetsam = [NSArray arrayWithArray:cargo]; // what the ship is carrying
[cargo removeAllObjects]; // dispense with it!
break;
}
// Throw out cargo
//
if (jetsam)
{
int n_jetsam = [jetsam count];
//
for (i = 0; i < n_jetsam; i++)
{
if (ranrot_rand() % 100 < cargo_chance) // chance of any given piece of cargo surviving decompression
{
ShipEntity* container = [jetsam objectAtIndex:i];
Vector rpos = xposition;
Vector rrand = randomPositionInBoundingBox(boundingBox);
rpos.x += rrand.x; rpos.y += rrand.y; rpos.z += rrand.z;
rpos.x += (ranrot_rand() % 7) - 3;
rpos.y += (ranrot_rand() % 7) - 3;
rpos.z += (ranrot_rand() % 7) - 3;
[container setPosition:rpos];
v.x = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
v.y = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
v.z = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
[container setVelocity:v];
quaternion_set_random(&q);
[container setQRotation:q];
[container setStatus:STATUS_IN_FLIGHT];
[container setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:container];
[[container getAI] setState:@"GLOBAL"];
}
}
}
// Throw out rocks and alloys to be scooped up
//
if ([roles isEqual:@"asteroid"])
{
if ((being_mined)||(randf() < 0.20))
{
int n_rocks = likely_cargo;
//
for (i = 0; i < n_rocks; i++)
{
ShipEntity* rock = [UNIVERSE newShipWithRole:@"boulder"]; // retain count = 1
if (rock)
{
Vector rpos = xposition;
int r_speed = 20.0 * [rock max_flight_speed];
int cr = 3 * rock->collision_radius;
rpos.x += (ranrot_rand() % cr) - cr/2;
rpos.y += (ranrot_rand() % cr) - cr/2;
rpos.z += (ranrot_rand() % cr) - cr/2;
[rock setPosition:rpos];
v.x = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.y = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.z = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
[rock setVelocity:v];
quaternion_set_random(&q);
[rock setQRotation:q];
[rock setStatus:STATUS_IN_FLIGHT];
[rock setScanClass: CLASS_ROCK];
[UNIVERSE addEntity:rock];
[[rock getAI] setState:@"GLOBAL"];
[rock release];
}
}
}
[UNIVERSE removeEntity:self];
return; // don't do anything more
}
if ([roles isEqual:@"boulder"])
{
if ((being_mined)||(ranrot_rand() % 100 < 20))
{
int n_rocks = 2 + (ranrot_rand() % 5);
//
for (i = 0; i < n_rocks; i++)
{
ShipEntity* rock = [UNIVERSE newShipWithRole:@"splinter"]; // retain count = 1
if (rock)
{
Vector rpos = xposition;
int r_speed = 20.0 * [rock max_flight_speed];
int cr = 3 * rock->collision_radius;
rpos.x += (ranrot_rand() % cr) - cr/2;
rpos.y += (ranrot_rand() % cr) - cr/2;
rpos.z += (ranrot_rand() % cr) - cr/2;
[rock setPosition:rpos];
v.x = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.y = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.z = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
[rock setBounty: 0];
[rock setCommodity:[UNIVERSE commodityForName:@"Minerals"] andAmount: 1];
[rock setVelocity:v];
quaternion_set_random(&q);
[rock setQRotation:q];
[rock setStatus:STATUS_IN_FLIGHT];
[rock setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:rock];
[[rock getAI] setState:@"GLOBAL"];
[rock release];
}
}
}
[UNIVERSE removeEntity:self];
return; // don't do anything more
}
// throw out burning chunks of wreckage
//
if (n_alloys && canFragment)
{
int n_wreckage = (n_alloys < 3)? n_alloys : 3;
// quick - check if UNIVERSE is nearing limit for entities - if it is don't make wreckage
//
add_more_explosion &= (UNIVERSE->n_entities < 0.50 * UNIVERSE_MAX_ENTITIES);
if (!add_more_explosion)
n_wreckage = 0;
//
////
for (i = 0; i < n_wreckage; i++)
{
ShipEntity* wreck = [UNIVERSE newShipWithRole:@"wreckage"]; // retain count = 1
if (wreck)
{
GLfloat expected_mass = 0.1f * mass * (0.75 + 0.5 * randf());
GLfloat wreck_mass = [wreck mass];
GLfloat scale_factor = powf(expected_mass / wreck_mass, 0.33333333f); // cube root of volume ratio
[wreck rescaleBy: scale_factor];
Vector r1 = randomFullNodeFrom([octree octreeDetails], kZeroVector);
Vector rpos = make_vector ( v_right.x * r1.x + v_up.x * r1.y + v_forward.x * r1.z,
v_right.y * r1.x + v_up.y * r1.y + v_forward.y * r1.z,
v_right.z * r1.x + v_up.z * r1.y + v_forward.z * r1.z);
rpos.x += xposition.x;
rpos.y += xposition.y;
rpos.z += xposition.z;
[wreck setPosition:rpos];
[wreck setVelocity:[self velocity]];
quaternion_set_random(&q);
[wreck setQRotation:q];
[wreck setTemperature: 1000.0]; // take 1000e heat damage per second
[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 performTumble];
[wreck release];
}
}
n_alloys = ranrot_rand() % n_alloys;
}
// Throw out scrap metal
//
for (i = 0; i < n_alloys; i++)
{
ShipEntity* plate = [UNIVERSE newShipWithRole:@"alloy"]; // retain count = 1
if (plate)
{
ShipEntity* container = [jetsam objectAtIndex:i];
Vector rpos = xposition;
Vector rrand = randomPositionInBoundingBox(boundingBox);
rpos.x += rrand.x; rpos.y += rrand.y; rpos.z += rrand.z;
rpos.x += (ranrot_rand() % 7) - 3;
rpos.y += (ranrot_rand() % 7) - 3;
rpos.z += (ranrot_rand() % 7) - 3;
[container setPosition:rpos];
[plate setPosition:rpos];
v.x = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
v.y = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
v.z = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
[container setVelocity:v];
[plate setVelocity:v];
quaternion_set_random(&q);
[container setQRotation:q];
[container setStatus:STATUS_IN_FLIGHT];
[container setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:container];
[[container getAI] setState:@"GLOBAL"];
[plate setQRotation:q];
[plate setScanClass: CLASS_CARGO];
[plate setCommodity:9 andAmount:1];
[UNIVERSE addEntity:plate];
[plate setStatus:STATUS_IN_FLIGHT];
[[plate getAI] setState:@"GLOBAL"];
[plate release];
}
}
}
// Throw out rocks and alloys to be scooped up
//
if ([roles isEqual:@"asteroid"])
{
if ((being_mined)||(randf() < 0.20))
{
int n_rocks = likely_cargo;
//
for (i = 0; i < n_rocks; i++)
{
ShipEntity* rock = [UNIVERSE newShipWithRole:@"boulder"]; // retain count = 1
if (rock)
{
Vector rpos = xposition;
int r_speed = 20.0 * [rock max_flight_speed];
int cr = 3 * rock->collision_radius;
rpos.x += (ranrot_rand() % cr) - cr/2;
rpos.y += (ranrot_rand() % cr) - cr/2;
rpos.z += (ranrot_rand() % cr) - cr/2;
[rock setPosition:rpos];
v.x = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.y = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.z = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
[rock setVelocity:v];
quaternion_set_random(&q);
[rock setQRotation:q];
[rock setStatus:STATUS_IN_FLIGHT];
[rock setScanClass: CLASS_ROCK];
[UNIVERSE addEntity:rock];
[[rock getAI] setState:@"GLOBAL"];
[rock release];
}
}
}
[UNIVERSE removeEntity:self];
return; // don't do anything more
}
if ([roles isEqual:@"boulder"])
{
if ((being_mined)||(ranrot_rand() % 100 < 20))
{
int n_rocks = 2 + (ranrot_rand() % 5);
//
for (i = 0; i < n_rocks; i++)
{
ShipEntity* rock = [UNIVERSE newShipWithRole:@"splinter"]; // retain count = 1
if (rock)
{
Vector rpos = xposition;
int r_speed = 20.0 * [rock max_flight_speed];
int cr = 3 * rock->collision_radius;
rpos.x += (ranrot_rand() % cr) - cr/2;
rpos.y += (ranrot_rand() % cr) - cr/2;
rpos.z += (ranrot_rand() % cr) - cr/2;
[rock setPosition:rpos];
v.x = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.y = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
v.z = 0.1 *((ranrot_rand() % r_speed) - r_speed / 2);
[rock setBounty: 0];
[rock setCommodity:[UNIVERSE commodityForName:@"Minerals"] andAmount: 1];
[rock setVelocity:v];
quaternion_set_random(&q);
[rock setQRotation:q];
[rock setStatus:STATUS_IN_FLIGHT];
[rock setScanClass: CLASS_CARGO];
[UNIVERSE addEntity:rock];
[[rock getAI] setState:@"GLOBAL"];
[rock release];
}
}
}
[UNIVERSE removeEntity:self];
return; // don't do anything more
}
// throw out burning chunks of wreckage
//
if (n_alloys && canFragment)
{
int n_wreckage = (n_alloys < 3)? n_alloys : 3;
// quick - check if UNIVERSE is nearing limit for entities - if it is don't make wreckage
//
add_more_explosion &= (UNIVERSE->n_entities < 0.50 * UNIVERSE_MAX_ENTITIES);
if (!add_more_explosion)
n_wreckage = 0;
//
////
for (i = 0; i < n_wreckage; i++)
{
ShipEntity* wreck = [UNIVERSE newShipWithRole:@"wreckage"]; // retain count = 1
if (wreck)
{
GLfloat expected_mass = 0.1f * mass * (0.75 + 0.5 * randf());
GLfloat wreck_mass = [wreck mass];
GLfloat scale_factor = powf(expected_mass / wreck_mass, 0.33333333f); // cube root of volume ratio
[wreck rescaleBy: scale_factor];
Vector r1 = randomFullNodeFrom([octree octreeDetails], kZeroVector);
Vector rpos = make_vector ( v_right.x * r1.x + v_up.x * r1.y + v_forward.x * r1.z,
v_right.y * r1.x + v_up.y * r1.y + v_forward.y * r1.z,
v_right.z * r1.x + v_up.z * r1.y + v_forward.z * r1.z);
rpos.x += xposition.x;
rpos.y += xposition.y;
rpos.z += xposition.z;
[wreck setPosition:rpos];
[wreck setVelocity:[self velocity]];
quaternion_set_random(&q);
[wreck setQRotation:q];
[wreck setTemperature: 1000.0]; // take 1000e heat damage per second
[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 performTumble];
[wreck release];
}
}
n_alloys = ranrot_rand() % n_alloys;
}
// Throw out scrap metal
//
for (i = 0; i < n_alloys; i++)
{
ShipEntity* plate = [UNIVERSE newShipWithRole:@"alloy"]; // retain count = 1
if (plate)
{
Vector rpos = xposition;
Vector rrand = randomPositionInBoundingBox(boundingBox);
rpos.x += rrand.x; rpos.y += rrand.y; rpos.z += rrand.z;
rpos.x += (ranrot_rand() % 7) - 3;
rpos.y += (ranrot_rand() % 7) - 3;
rpos.z += (ranrot_rand() % 7) - 3;
[plate setPosition:rpos];
v.x = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
v.y = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
v.z = 0.1 *((ranrot_rand() % speed_low) - speed_low / 2);
[plate setVelocity:v];
quaternion_set_random(&q);
[plate setQRotation:q];
[plate setScanClass: CLASS_CARGO];
[plate setCommodity:9 andAmount:1];
[UNIVERSE addEntity:plate];
[plate setStatus:STATUS_IN_FLIGHT];
[[plate getAI] setState:@"GLOBAL"];
[plate release];
}
}
}
//
@ -4233,10 +4244,13 @@ static GLfloat mascem_color2[4] = { 0.4, 0.1, 0.4, 1.0}; // purple
Entity* se = (Entity *)[sub_entities objectAtIndex:i];
if (se->isShip)
{
Vector origin = [(ShipEntity*)se absolutePositionForSubentity];
[se setPosition:origin]; // is this what's messing thing up??
[UNIVERSE addEntity:se];
[(ShipEntity *)se becomeExplosion];
ShipEntity *sse = (ShipEntity *)se;
Vector pos = [sse absolutePositionForSubentity];
[sse setSuppressExplosion:suppressExplosion];
[sse setPosition:pos]; // is this what's messing thing up??
[UNIVERSE addEntity:sse];
[sse becomeExplosion];
}
}
[sub_entities release]; // releases each subentity too!
@ -4316,6 +4330,7 @@ Vector randomPositionInBoundingBox(BoundingBox bb)
return result;
}
Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q, NSString* align)
{
NSString* padAlign = [NSString stringWithFormat:@"%@---", align];
@ -4366,6 +4381,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
return result;
}
- (void) becomeLargeExplosion:(double) factor
{
Vector xposition = position;
@ -4466,6 +4482,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
[UNIVERSE removeEntity:self];
}
- (void) collectBountyFor:(ShipEntity *)other
{
if ([roles isEqual:@"pirate"])
@ -4489,6 +4506,12 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
return ship_temperature / (GLfloat)SHIP_MAX_CABIN_TEMP;
}
- (void)setSuppressExplosion:(BOOL)suppress
{
suppressExplosion = suppress != NO;
}
/*-----------------------------------------
AI piloting methods
@ -6176,12 +6199,8 @@ BOOL class_masslocks(int some_class)
}
if (ent->isPlanet)
{
if (isPlayer)
{
[(PlayerEntity *)self getDestroyed];
return;
}
[self becomeExplosion];
[self getDestroyedBy:ent context:@"hit a planet"];
if (self == [PlayerEntity sharedPlayer]) [self retain];
}
if (ent->isWormhole)
{
@ -6201,6 +6220,7 @@ BOOL class_masslocks(int some_class)
}
}
- (BOOL) collideWithShip:(ShipEntity *)other
{
Vector loc, opos, pos;
@ -6543,7 +6563,7 @@ BOOL class_masslocks(int some_class)
BOOL iAmTheLaw = (scanClass == CLASS_POLICE);
BOOL uAreTheLaw = ((other)&&(other->scanClass == CLASS_POLICE));
//
energy -= amount;
being_mined = NO;
//

View File

@ -3944,9 +3944,6 @@ static BOOL MaintainLinkedLists(Universe* uni)
{
if (entity)
{
if (debug & DEBUG_ENTITIES)
NSLog(@"DEBUG --(%@) from %d", entity, entity->zero_index);
// remove reference to entity in linked lists
if ([entity canCollide]) // filter only collidables disappearing
doLinkedListMaintenanceThisUpdate = YES;
@ -5018,7 +5015,6 @@ static BOOL MaintainLinkedLists(Universe* uni)
sky_clear_color[3] = 0.0;
// use a retained copy so this can't be changed under us.
for (i = 0; i < ent_count; i++)
my_entities[i] = [sortedEntities[i] retain]; // explicitly retain each one
@ -5026,75 +5022,69 @@ static BOOL MaintainLinkedLists(Universe* uni)
universal_time += delta_t;
update_stage = @"demo management";
if ((demo_stage)&&(player)&&(inGUIMode )&&(universal_time > demo_stage_time)&&([player gui_screen] == GUI_SCREEN_INTRO2))
if ((demo_stage)&&(player)&&(inGUIMode)&&(universal_time > demo_stage_time)&&([player gui_screen] == GUI_SCREEN_INTRO2))
{
if (ent_count > 1)
{
Vector vel;
Quaternion q2;
q2.x = 0.0; q2.y = 0.0; q2.z = 0.0; q2.w = 1.0;
Vector vel;
Quaternion q2 = kIdentityQuaternion;
quaternion_rotate_about_y(&q2,M_PI);
#define DEMO2_VANISHING_DISTANCE 400.0
switch (demo_stage)
{
case DEMO_FLY_IN :
vel.x = 0.0; vel.y = 0.0; vel.z = 0.0;
if (demo_ship)
{
[demo_ship setVelocity:vel];
[demo_ship setPosition:[demo_ship destination]]; // ideal position
}
case DEMO_FLY_IN:
[demo_ship setVelocity:kZeroVector];
[demo_ship setPosition:[demo_ship destination]]; // ideal position
demo_stage = DEMO_SHOW_THING;
demo_stage_time = universal_time + 6.0;
break;
case DEMO_SHOW_THING :
if (demo_ship)
{
vel.x = 0.0; vel.y = 0.0; vel.z = 3.6 * demo_ship->actual_radius * 100.0;
[demo_ship setVelocity:vel];
}
case DEMO_SHOW_THING:
vel = make_vector(0, 0, DEMO2_VANISHING_DISTANCE * demo_ship->actual_radius);
[demo_ship setVelocity:vel];
demo_stage = DEMO_FLY_OUT;
demo_stage_time = universal_time + 1.5;
break;
case DEMO_FLY_OUT :
case DEMO_FLY_OUT:
// change the demo_ship here
demo_ship_index++;
demo_ship_index %= [demo_ships count];
if (demo_ship)
[self removeEntity:demo_ship];
demo_ship = nil;
NSString *shipDesc = nil;
NSDictionary *shipDict = nil;
demo_ship_index = (demo_ship_index + 1) % [demo_ships count];
shipDesc = [demo_ships objectAtIndex:demo_ship_index];
if ([shipDesc isKindOfClass:[NSString class]])
{
BOOL okay = YES;
do
shipDict = [self getDictionaryForShip:shipDesc];
if (shipDict)
{
NS_DURING
okay = YES;
[demo_ship setUpShipFromDictionary:[self getDictionaryForShip:[demo_ships objectAtIndex:demo_ship_index]]];
NS_HANDLER
if ([[localException name] isEqual: OOLITE_EXCEPTION_DATA_NOT_FOUND])
{
// we want to skip on to another ship
demo_ship_index++;
demo_ship_index %= [demo_ships count];
OOLog(kOOLogException, @"***** Oolite Data Not Found Exception : '%@' in DEMO_FLY_OUT stage of [Universe update:] *****", [localException reason]);
okay = NO;
}
else
[localException raise];
NS_ENDHANDLER
} while (!okay);
// Failure means we don't change demo_stage, so we'll automatically try again.
demo_ship = [[ShipEntity alloc] initWithDictionary:shipDict];
}
}
if (demo_ship != nil)
{
[self addEntity:demo_ship];
[[demo_ship getAI] setStateMachine:@"nullAI.plist"];
[demo_ship setQRotation:q2];
[demo_ship setPositionX:0.0f y:0.0f z:360.0f * demo_ship->actual_radius];
[demo_ship setDestination: make_vector( 0.0f, 0.0f, 3.6f * demo_ship->actual_radius)]; // ideal position
vel.x = 0.0; vel.y = 0.0; vel.z = -360.0f * demo_ship->actual_radius;
[demo_ship setPositionX:0.0f y:0.0f z:DEMO2_VANISHING_DISTANCE * demo_ship->actual_radius];
[demo_ship setDestination: make_vector( 0.0f, 0.0f, DEMO2_VANISHING_DISTANCE * 0.01f * demo_ship->actual_radius)]; // ideal position
vel = make_vector(0, 0, -DEMO2_VANISHING_DISTANCE * demo_ship->actual_radius);
[demo_ship setVelocity:vel];
[demo_ship setScanClass: CLASS_NO_DRAW];
[demo_ship setRoll:M_PI/5.0];
[demo_ship setPitch:M_PI/10.0];
[gui setText:[demo_ship name] forRow:19 align:GUI_ALIGN_CENTER];
demo_stage = DEMO_FLY_IN;
demo_stage_time = universal_time + 1.5;
}
demo_stage = DEMO_FLY_IN;
demo_stage_time = universal_time + 1.5;
break;
}
}