Introduce Javascript-based frame-by-frame AI management

Add ship.max(Pitch|Roll|Yaw) properties
Modify player.ship.(Pitch|Roll|Yaw) properties so that signs reported are the same as for NPC ships.


git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@5190 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Chris Morris 2012-08-16 19:33:38 +00:00
parent 50e44e796c
commit 0db1d55fb6
7 changed files with 178 additions and 1 deletions

View File

@ -109,6 +109,8 @@
"performCollect",
"performIntercept",
"performFlee",
"performScriptedAI",
"performScriptedAttackAI",
"getWitchspaceEntryCoordinates",
"setDestinationFromCoordinates",
"setCoordinatesFromPosition",

View File

@ -653,6 +653,7 @@ typedef enum
- (void) behaviour_avoid_collision:(double) delta_t;
- (void) behaviour_track_as_turret:(double) delta_t;
- (void) behaviour_fly_thru_navpoints:(double) delta_t;
- (void) behaviour_scripted_ai:(double) delta_t;
- (GLfloat *) scannerDisplayColorForShip:(ShipEntity*)otherShip :(BOOL)isHostile :(BOOL)flash :(OOColor *)scannerDisplayColor1 :(OOColor *)scannerDisplayColor2;
- (void)setScannerDisplayColor1:(OOColor *)color1;
@ -834,7 +835,10 @@ typedef enum
- (GLfloat) flightPitch;
- (GLfloat) flightYaw;
- (GLfloat) flightSpeed;
- (GLfloat) maxFlightPitch;
- (GLfloat) maxFlightSpeed;
- (GLfloat) maxFlightRoll;
- (GLfloat) maxFlightYaw;
- (GLfloat) speedFactor;
- (GLfloat) temperature;

View File

@ -2347,6 +2347,11 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
[self behaviour_fly_thru_navpoints: delta_t];
break;
case BEHAVIOUR_SCRIPTED_AI:
case BEHAVIOUR_SCRIPTED_ATTACK_AI:
[self behaviour_scripted_ai: delta_t];
break;
case BEHAVIOUR_ENERGY_BOMB_COUNTDOWN:
applyThrust = NO;
// Do nothing
@ -5208,6 +5213,100 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other)
}
- (void) behaviour_scripted_ai:(double) delta_t
{
JSContext *context = OOJSAcquireContext();
jsval rval = JSVAL_VOID;
jsval args[] = { OOJSValueFromNativeObject(context, [NSNumber numberWithFloat:delta_t]) };
NSDictionary *result;
BOOL OK = [[self script] callMethod:OOJSID("scriptedAI") inContext:context withArguments:args count:1 result:&rval];
if (!OK)
{
OOLog(@"ai.error",@"Could not call scriptedAI in ship script of %@, reverting to idle",self);
behaviour = BEHAVIOUR_IDLE;
OOJSRelinquishContext(context);
return;
}
if (!JSVAL_IS_OBJECT(rval))
{
OOLog(@"ai.error",@"Invalid return value of scriptedAI in ship script of %@, reverting to idle",self);
behaviour = BEHAVIOUR_IDLE;
OOJSRelinquishContext(context);
return;
}
result = OOJSNativeObjectFromJSObject(context, JSVAL_TO_OBJECT(rval));
OOJSRelinquishContext(context);
stick_roll = [result oo_floatForKey:@"stickRoll" defaultValue:0.0];
if (stick_roll > max_flight_roll)
{
stick_roll = max_flight_roll;
}
else if (stick_roll < -max_flight_roll)
{
stick_roll = -max_flight_roll;
}
stick_pitch = [result oo_floatForKey:@"stickPitch" defaultValue:0.0];
if (stick_pitch > max_flight_pitch)
{
stick_pitch = max_flight_pitch;
}
else if (stick_pitch < -max_flight_pitch)
{
stick_pitch = -max_flight_pitch;
}
stick_yaw = [result oo_floatForKey:@"stickYaw" defaultValue:0.0];
if (stick_yaw > max_flight_yaw)
{
stick_yaw = max_flight_yaw;
}
else if (stick_yaw < -max_flight_yaw)
{
stick_yaw = -max_flight_yaw;
}
[self applySticks:delta_t];
desired_speed = [result oo_floatForKey:@"desiredSpeed" defaultValue:0.0];
if (desired_speed < 0.0)
{
desired_speed = 0.0;
}
// overspeed is handled by applyThrust
if (behaviour == BEHAVIOUR_SCRIPTED_ATTACK_AI)
{
NSString* chosen_weapon = [result oo_stringForKey:@"chosenWeapon" defaultValue:@"FORWARD"];
double range = [self rangeToPrimaryTarget];
if ([chosen_weapon isEqualToString:@"FORWARD"])
{
[self fireMainWeapon:range];
}
else if ([chosen_weapon isEqualToString:@"AFT"])
{
[self fireAftWeapon:range];
}
else if ([chosen_weapon isEqualToString:@"PORT"])
{
[self firePortWeapon:range];
}
else if ([chosen_weapon isEqualToString:@"STARBOARD"])
{
[self fireStarboardWeapon:range];
}
}
}
- (void)drawEntity:(BOOL)immediate :(BOOL)translucent
{
if ((no_draw_distance < cam_zero_distance) || // Done redundantly to skip subentities
@ -6062,6 +6161,7 @@ static BOOL IsBehaviourHostile(OOBehaviour behaviour)
case BEHAVIOUR_ATTACK_BROADSIDE_RIGHT:
case BEHAVIOUR_CLOSE_TO_BROADSIDE_RANGE:
case BEHAVIOUR_ATTACK_SNIPER:
case BEHAVIOUR_SCRIPTED_ATTACK_AI:
return YES;
default:
@ -7042,12 +7142,30 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
}
- (GLfloat) maxFlightPitch
{
return max_flight_pitch;
}
- (GLfloat) maxFlightSpeed
{
return maxFlightSpeed;
}
- (GLfloat) maxFlightRoll
{
return max_flight_roll;
}
- (GLfloat) maxFlightYaw
{
return max_flight_yaw;
}
- (GLfloat) speedFactor
{
if (maxFlightSpeed <= 0.0) return 0.0;
@ -7246,7 +7364,7 @@ NSComparisonResult ComparePlanetsBySurfaceDistance(id i1, id i2, void* context)
if ([entity isShip]) {
// ShipEntity* attacker = (ShipEntity *)entity;
if ([self hasHostileTarget] && accuracy >= COMBAT_AI_IS_SMART && (randf()*10.0 < accuracy || desired_speed < 0.5 * maxFlightSpeed) && behaviour != BEHAVIOUR_EVASIVE_ACTION && behaviour != BEHAVIOUR_FLEE_EVASIVE_ACTION)
if ([self hasHostileTarget] && accuracy >= COMBAT_AI_IS_SMART && (randf()*10.0 < accuracy || desired_speed < 0.5 * maxFlightSpeed) && behaviour != BEHAVIOUR_EVASIVE_ACTION && behaviour != BEHAVIOUR_FLEE_EVASIVE_ACTION && behaviour != BEHAVIOUR_SCRIPTED_ATTACK_AI)
{
if (behaviour == BEHAVIOUR_FLEE_TARGET)
{

View File

@ -123,6 +123,9 @@
- (void) performFlee;
- (void) performScriptedAI;
- (void) performScriptedAttackAI;
- (void) requestDockingCoordinates;
- (void) getWitchspaceEntryCoordinates;
@ -825,6 +828,20 @@
}
- (void) performScriptedAI
{
behaviour = BEHAVIOUR_SCRIPTED_AI;
frustration = 0.0;
}
- (void) performScriptedAttackAI
{
behaviour = BEHAVIOUR_SCRIPTED_ATTACK_AI;
frustration = 0.0;
}
- (void) getWitchspaceEntryCoordinates
{
/*- calculates coordinates from the nearest station it can find, or just fly 10s forward -*/

View File

@ -112,8 +112,10 @@ enum
kPlayerShip_hudHidden, // hud visibility, boolean, read/write
kPlayerShip_maxAftShield, // maximum aft shield charge level, positive float, read-only
kPlayerShip_maxForwardShield, // maximum forward shield charge level, positive float, read-only
kPlayerShip_pitch, // pitch (overrules Ship)
kPlayerShip_price, // idealised trade-in value decicredits, positive int, read-only
kPlayerShip_reticleTargetSensitive, // target box changes color when primary target in crosshairs, boolean, read/write
kPlayerShip_roll, // roll (overrules Ship)
kPlayerShip_scoopOverride, // Scooping
kPlayerShip_serviceLevel, // servicing level, positive int 75-100, read-only
kPlayerShip_specialCargo, // special cargo, string, read-only
@ -121,6 +123,7 @@ enum
kPlayerShip_viewDirection, // view direction identifier, string, read-only
// kPlayerShip_weaponFacings, // available weapon facings, int, read-only
kPlayerShip_weaponsOnline, // weapons online status, boolean, read-only
kPlayerShip_yaw, // yaw (overrules Ship)
};
@ -151,7 +154,9 @@ static JSPropertySpec sPlayerShipProperties[] =
{ "maxAftShield", kPlayerShip_maxAftShield, OOJS_PROP_READONLY_CB },
{ "maxForwardShield", kPlayerShip_maxForwardShield, OOJS_PROP_READONLY_CB },
{ "price", kPlayerShip_price, OOJS_PROP_READONLY_CB },
{ "pitch", kPlayerShip_pitch, OOJS_PROP_READONLY_CB },
{ "reticleTargetSensitive", kPlayerShip_reticleTargetSensitive, OOJS_PROP_READWRITE_CB },
{ "roll", kPlayerShip_roll, OOJS_PROP_READONLY_CB },
{ "scoopOverride", kPlayerShip_scoopOverride, OOJS_PROP_READWRITE_CB },
{ "serviceLevel", kPlayerShip_serviceLevel, OOJS_PROP_READWRITE_CB },
{ "specialCargo", kPlayerShip_specialCargo, OOJS_PROP_READONLY_CB },
@ -159,6 +164,7 @@ static JSPropertySpec sPlayerShipProperties[] =
{ "viewDirection", kPlayerShip_viewDirection, OOJS_PROP_READONLY_CB },
// { "weaponFacings", kPlayerShip_weaponFacings, OOJS_PROP_READONLY_CB },
{ "weaponsOnline", kPlayerShip_weaponsOnline, OOJS_PROP_READONLY_CB },
{ "yaw", kPlayerShip_yaw, OOJS_PROP_READONLY_CB },
{ 0 }
};
@ -391,6 +397,18 @@ static JSBool PlayerShipGetProperty(JSContext *context, JSObject *this, jsid pro
case kPlayerShip_serviceLevel:
return JS_NewNumberValue(context, [player tradeInFactor], value);
// make roll, pitch, yaw reported to JS use same +/- convention as
// for NPC ships
case kPlayerShip_pitch:
return JS_NewNumberValue(context, -[player flightPitch], value);
case kPlayerShip_roll:
return JS_NewNumberValue(context, -[player flightRoll], value);
case kPlayerShip_yaw:
return JS_NewNumberValue(context, -[player flightYaw], value);
default:
OOJSReportBadPropertySelector(context, this, propID, sPlayerShipProperties);
}

View File

@ -171,7 +171,10 @@ enum
kShip_laserHeatLevelPort, // port laser temperature, float, read-only
kShip_laserHeatLevelStarboard, // starboard laser temperature, float, read-only
kShip_lightsActive, // flasher/shader light flag, boolean, read/write
kShip_maxPitch, // maximum flight pitch, double, read-only
kShip_maxSpeed, // maximum flight speed, double, read-only
kShip_maxRoll, // maximum flight roll, double, read-only
kShip_maxYaw, // maximum flight yaw, double, read-only
kShip_maxThrust, // maximum thrust, double, read-only
kShip_missileCapacity, // max missiles capacity, integer, read-only
kShip_missileLoadTime, // missile load time, double, read/write
@ -275,7 +278,10 @@ static JSPropertySpec sShipProperties[] =
{ "laserHeatLevelPort", kShip_laserHeatLevelPort, OOJS_PROP_READONLY_CB },
{ "laserHeatLevelStarboard", kShip_laserHeatLevelStarboard, OOJS_PROP_READONLY_CB },
{ "lightsActive", kShip_lightsActive, OOJS_PROP_READWRITE_CB },
{ "maxPitch", kShip_maxPitch, OOJS_PROP_READONLY_CB },
{ "maxSpeed", kShip_maxSpeed, OOJS_PROP_READONLY_CB },
{ "maxRoll", kShip_maxRoll, OOJS_PROP_READONLY_CB },
{ "maxYaw", kShip_maxYaw, OOJS_PROP_READONLY_CB },
{ "maxThrust", kShip_maxThrust, OOJS_PROP_READONLY_CB },
{ "missileCapacity", kShip_missileCapacity, OOJS_PROP_READONLY_CB },
{ "missileLoadTime", kShip_missileLoadTime, OOJS_PROP_READWRITE_CB },
@ -588,8 +594,17 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsid propID, j
case kShip_desiredSpeed:
return JS_NewNumberValue(context, [entity desiredSpeed], value);
case kShip_maxPitch:
return JS_NewNumberValue(context, [entity maxFlightPitch], value);
case kShip_maxSpeed:
return JS_NewNumberValue(context, [entity maxFlightSpeed], value);
case kShip_maxRoll:
return JS_NewNumberValue(context, [entity maxFlightRoll], value);
case kShip_maxYaw:
return JS_NewNumberValue(context, [entity maxFlightYaw], value);
case kShip_script:
result = [entity shipScript];

View File

@ -55,3 +55,6 @@ ENTRY(BEHAVIOUR_FORMATION_BREAK, 502)
ENTRY(BEHAVIOUR_ENERGY_BOMB_COUNTDOWN, 601)
ENTRY(BEHAVIOUR_TRACTORED, 701)
ENTRY(BEHAVIOUR_SCRIPTED_AI, 801)
ENTRY(BEHAVIOUR_SCRIPTED_ATTACK_AI, 811)