From 2837bb87b6fdade78075c1adc99b24f7b42fb69c Mon Sep 17 00:00:00 2001 From: Chris Morris Date: Tue, 5 Jun 2012 18:42:19 +0000 Subject: [PATCH] Wormhole exit speed fixed per wormhole (all to the same value for now) Sniper behaviour usable by high accuracy ships with long-range weapons git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@4985 127b21dd-08f5-0310-b4b7-95ae10353056 --- src/Core/Entities/PlayerEntity.m | 7 +- src/Core/Entities/ShipEntity.h | 4 +- src/Core/Entities/ShipEntity.m | 101 +++++++++++++++++++++++++++-- src/Core/Entities/WormholeEntity.h | 3 + src/Core/Entities/WormholeEntity.m | 9 ++- src/Core/Tables/OOBehaviour.tbl | 2 +- 6 files changed, 113 insertions(+), 13 deletions(-) diff --git a/src/Core/Entities/PlayerEntity.m b/src/Core/Entities/PlayerEntity.m index 82d1132a..cbfe7211 100644 --- a/src/Core/Entities/PlayerEntity.m +++ b/src/Core/Entities/PlayerEntity.m @@ -5371,7 +5371,6 @@ static GLfloat sBaseMass = 0.0; { // player is not allone in his wormhole, synchronise player and wormhole position. double wh_arrival_time = ([PLAYER clockTimeAdjusted] - [wormhole arrivalTime]); - Vector distance; if (wh_arrival_time > 0) { // Player is following other ship @@ -5383,7 +5382,8 @@ static GLfloat sBaseMass = 0.0; whpos = vector_add(exitpos, vector_multiply_scalar([self forwardVector], -500.0f)); } - distance = vector_subtract(whpos, pos); + + Vector distance = vector_subtract(whpos, pos); if (magnitude2(distance) < MIN_DISTANCE_TO_BUOY2 ) // within safety distance from the buoy? { // the wormhole is to close to the buoy. Move both player and wormhole away from it in the x-y plane. @@ -5394,13 +5394,14 @@ static GLfloat sBaseMass = 0.0; } [wormhole setExitPosition: whpos]; } + flightSpeed = [wormhole exitSpeed]; [wormhole release]; wormhole = nil; flightRoll = 0.0f; flightPitch = 0.0f; flightYaw = 0.0f; - flightSpeed = fmin(maxFlightSpeed,50.0f); + velocity = kZeroVector; [self setStatus:STATUS_EXITING_WITCHSPACE]; gui_screen = GUI_SCREEN_MAIN; diff --git a/src/Core/Entities/ShipEntity.h b/src/Core/Entities/ShipEntity.h index e3333858..5ee0daae 100644 --- a/src/Core/Entities/ShipEntity.h +++ b/src/Core/Entities/ShipEntity.h @@ -124,8 +124,9 @@ OOJSScript, OORoleSet, OOShipGroup, OOEquipmentType; #define COMBAT_AI_WEAPON_TEMP_USABLE WEAPON_COOLING_CUTOUT * NPC_MAX_WEAPON_TEMP #define COMBAT_AI_ISNT_AWFUL 0.0f #define COMBAT_AI_IS_SMART 5.0f -#define COMBAT_AI_TRACKS_CLOSER 7.5f #define COMBAT_AI_FLEES_BETTER 6.0f +#define COMBAT_AI_TRACKS_CLOSER 7.5f +#define COMBAT_AI_USES_SNIPING 8.5f #define COMBAT_AI_FLEES_BETTER_2 9.0f @@ -632,6 +633,7 @@ _lightsActive: 1; - (void) behaviour_attack_broadside_right:(double) delta_t; - (void) behaviour_close_to_broadside_range:(double) delta_t; - (void) behaviour_attack_broadside_target:(double) delta_t leftside:(BOOL)leftside; +- (void) behaviour_attack_sniper:(double) delta_t; - (void) behaviour_fly_range_from_destination:(double) delta_t; - (void) behaviour_face_destination:(double) delta_t; - (void) behaviour_land_on_planet:(double) delta_t; diff --git a/src/Core/Entities/ShipEntity.m b/src/Core/Entities/ShipEntity.m index 34c1d5a1..7c903c3f 100644 --- a/src/Core/Entities/ShipEntity.m +++ b/src/Core/Entities/ShipEntity.m @@ -2179,6 +2179,10 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) [self behaviour_close_to_broadside_range: delta_t]; break; + case BEHAVIOUR_ATTACK_SNIPER : + [self behaviour_attack_sniper: delta_t]; + break; + case BEHAVIOUR_EVASIVE_ACTION : case BEHAVIOUR_FLEE_EVASIVE_ACTION : [self behaviour_evasive_action: delta_t]; @@ -3644,11 +3648,14 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) else if (forward_weapon_ready) { jink = kZeroVector; // almost all behaviours + double aspect = [self approachAspectToPrimaryTarget]; // TODO: good pilots use behaviour_attack_sniper sometimes - - double aspect = [self approachAspectToPrimaryTarget]; - if (accuracy >= COMBAT_AI_ISNT_AWFUL && aspect < 0) + if (getWeaponRangeFromType(forward_weapon_real_type) > getWeaponRangeFromType(WEAPON_PULSE_LASER) && range > getWeaponRangeFromType(WEAPON_PULSE_LASER)) + { + behaviour = BEHAVIOUR_ATTACK_SNIPER; + } + else if (accuracy >= COMBAT_AI_ISNT_AWFUL && aspect < 0) { behaviour = BEHAVIOUR_ATTACK_FLY_TO_TARGET_SIX; } @@ -3674,6 +3681,8 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) } } + if ([UNIVERSE entityForUniversalID:[PLAYER primaryTargetID]] == self) OOLog(@"new.behaviour",@"%d",behaviour); + frustration = 0.0; // behaviour changed, so reset frustration [self applyAttitudeChanges:delta_t]; @@ -3925,6 +3934,72 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) } +- (void) behaviour_attack_sniper:(double) delta_t +{ + double range = [self rangeToPrimaryTarget]; + float max_available_speed = maxFlightSpeed; + + if (range < getWeaponRangeFromType(WEAPON_PULSE_LASER)) + { + behaviour = BEHAVIOUR_ATTACK_TARGET; + } + else + { + if (range > weaponRange) + { + desired_speed = max_available_speed; + } + else + { + desired_speed = max_available_speed / 10.0f; + } + + double last_success_factor = success_factor; + success_factor = [self trackPrimaryTarget:delta_t:NO]; + + if ((success_factor > 0.999)||(success_factor > last_success_factor)) + { + frustration -= delta_t; + if (frustration < 0.0) + frustration = 0.0; + } + else + { + frustration += delta_t; + if (frustration > 3.0) // 3s of frustration + { + [shipAI reactToMessage:@"FRUSTRATED" context:@"BEHAVIOUR_ATTACK_SNIPER"]; + [self setEvasiveJink:1000.0]; + behaviour = BEHAVIOUR_ATTACK_TARGET; + frustration = 0.0; + desired_speed = maxFlightSpeed; + } + } + + } + + int missile_chance = 0; + int rhs = 3.2 / delta_t; + if (rhs) missile_chance = 1 + (ranrot_rand() % rhs); + + double hurt_factor = 16 * pow(energy/maxEnergy, 4.0); + if (missiles > missile_chance * hurt_factor) + { + [self fireMissile]; + } + if (cloakAutomatic) [self activateCloakingDevice]; + [self fireMainWeapon:range]; + [self applyAttitudeChanges:delta_t]; + [self applyThrust:delta_t]; + + if (weapon_temp > COMBAT_AI_WEAPON_TEMP_USABLE && accuracy >= COMBAT_AI_ISNT_AWFUL) + { + behaviour = BEHAVIOUR_ATTACK_TARGET; + } + +} + + - (void) behaviour_fly_to_target_six:(double) delta_t { BOOL canBurn = [self hasFuelInjection] && (fuel > MIN_FUEL); @@ -3981,7 +4056,7 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) { if (range < back_off_range) { - desired_speed = fmax(0.9 * target_speed, 0.4 * maxFlightSpeed); + desired_speed = fmax(0.9 * target_speed, 0.8 * maxFlightSpeed); } else { @@ -4031,12 +4106,15 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) destination = [target distance_twelve:1250 withOffset:0]; } } - + + pitching_over = NO; // in case it's set from elsewhere double confidenceFactor = [self trackDestination:delta_t :NO]; if(success_factor > last_success_factor || confidenceFactor < 0.85) frustration += delta_t; else if(frustration > 0.0) frustration -= delta_t * 0.75; - if(frustration > 10) + + double aspect = [self approachAspectToPrimaryTarget]; + if(frustration > 10 || aspect > 0.75) { behaviour = BEHAVIOUR_ATTACK_TARGET; } @@ -4151,6 +4229,9 @@ ShipEntity* doOctreesCollide(ShipEntity* prime, ShipEntity* other) desired_speed = max_available_speed; // use afterburner to approach } + if ([UNIVERSE entityForUniversalID:[PLAYER primaryTargetID]] == self) OOLog(@"new.behaviour.speed",@"%f (c:%f)",desired_speed,flightSpeed); + + double last_success_factor = success_factor; success_factor = [self trackPrimaryTarget:delta_t:NO]; // do the actual piloting if ((success_factor > 0.999)||(success_factor > last_success_factor)) @@ -5631,6 +5712,7 @@ static BOOL IsBehaviourHostile(OOBehaviour behaviour) case BEHAVIOUR_ATTACK_BROADSIDE_LEFT: case BEHAVIOUR_ATTACK_BROADSIDE_RIGHT: case BEHAVIOUR_CLOSE_TO_BROADSIDE_RANGE: + case BEHAVIOUR_ATTACK_SNIPER: return YES; default: @@ -8064,6 +8146,11 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q } int max_factor = 8; double r_max_factor = 0.125; + if (accuracy >= COMBAT_AI_TRACKS_CLOSER && max_flight_pitch > 1.0) + { + max_factor = floor(max_flight_pitch/0.125); + r_max_factor = 1.0/max_factor; + } d_right = dot_product(relPos, v_right); d_up = dot_product(relPos, v_up); @@ -8369,7 +8456,6 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q // end rule-of-thumb manoeuvres -// TODO: check this // apply damping if (flightRoll < 0) flightRoll += (flightRoll < -damping) ? damping : -flightRoll; @@ -10584,6 +10670,7 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q flightSpeed = 50.0; // constant speed same for all ships // was a quarter of max speed, so the Anaconda speeds up and most // others slow down - CIM +// will be overridden if left witchspace via a genuine wormhole velocity = kZeroVector; if (![UNIVERSE addEntity:self]) // AI and status get initialised here { diff --git a/src/Core/Entities/WormholeEntity.h b/src/Core/Entities/WormholeEntity.h index 6e5ab031..5574a701 100644 --- a/src/Core/Entities/WormholeEntity.h +++ b/src/Core/Entities/WormholeEntity.h @@ -61,6 +61,8 @@ typedef enum double witch_mass; double shrink_factor; // used during nova mission +// not used yet +// double exit_speed; // exit speed of ships in this wormhole WORMHOLE_SCANINFO scan_info; BOOL hasExitPosition; @@ -82,6 +84,7 @@ typedef enum - (void) setMisjump; // Flags up a wormhole as 'misjumpy' - (BOOL) withMisjump; +- (double) exitSpeed; // exit speed from this wormhole - (double) expiryTime; // Time at which the wormholes entrance closes - (double) arrivalTime; // Time at which the wormholes exit opens - (double) estimatedArrivalTime; // Time when wormhole should open (different from arrival_time for misjump wormholes) diff --git a/src/Core/Entities/WormholeEntity.m b/src/Core/Entities/WormholeEntity.m index 2b99c932..b04be610 100644 --- a/src/Core/Entities/WormholeEntity.m +++ b/src/Core/Entities/WormholeEntity.m @@ -320,10 +320,11 @@ static void DrawWormholeCorona(GLfloat inner_radius, GLfloat outer_radius, int s [ship setOrientation: [UNIVERSE getWitchspaceExitRotation]]; [ship setPitch: 0.0]; [ship setRoll: 0.0]; - [ship setSpeed: [ship maxFlightSpeed] * 0.25]; [ship setVelocity: kZeroVector]; [UNIVERSE addEntity:ship]; // AI and status get initialised here } + [ship setSpeed:[self exitSpeed]]; // all ships from this wormhole have same velocity + // Should probably pass the wormhole, but they have no JS representation [ship doScriptEvent:OOJSID("shipExitedWormhole") andReactToAIMessage:@"EXITED WITCHSPACE"]; @@ -382,6 +383,12 @@ static void DrawWormholeCorona(GLfloat inner_radius, GLfloat outer_radius, int s return destinationCoords; } +- (double) exitSpeed +{ + // return exit_speed; // later + return 50.0; +} + - (double) expiryTime { return expiry_time; diff --git a/src/Core/Tables/OOBehaviour.tbl b/src/Core/Tables/OOBehaviour.tbl index a8f1a7bb..9593d5d9 100644 --- a/src/Core/Tables/OOBehaviour.tbl +++ b/src/Core/Tables/OOBehaviour.tbl @@ -24,7 +24,7 @@ ENTRY(BEHAVIOUR_ATTACK_BREAK_OFF_TARGET, 110) // further advanced combat... ENTRY(BEHAVIOUR_ATTACK_FLY_TO_TARGET_TWELVE,112) -// ENTRY(BEHAVIOUR_ATTACK_SNIPER, 113) +ENTRY(BEHAVIOUR_ATTACK_SNIPER, 113) // side weapon combat... ENTRY(BEHAVIOUR_ATTACK_BROADSIDE,115)