Set up multiple laser usage

This commit is contained in:
cim 2015-08-22 14:24:49 +01:00
parent 428a32587a
commit cb97021d18
2 changed files with 110 additions and 78 deletions

View File

@ -5668,7 +5668,14 @@ NSComparisonResult marketSorterByMassUnit(id a, id b, void *market);
[self currentWeaponStats];
if (energy <= weapon_energy_use)
NSUInteger multiplier = 1;
if (_multiplyWeapons)
{
// multiple fitted
multiplier = [[self laserPortOffset:currentWeaponFacing] count];
}
if (energy <= weapon_energy_use * multiplier)
{
[UNIVERSE addMessage:DESC(@"weapon-out-of-juice") forCount:3.0];
return NO;
@ -5676,27 +5683,27 @@ NSComparisonResult marketSorterByMassUnit(id a, id b, void *market);
using_mining_laser = [weapon_to_be_fired isMiningLaser];
energy -= weapon_energy_use;
energy -= weapon_energy_use * multiplier;
switch (currentWeaponFacing)
{
case WEAPON_FACING_FORWARD:
forward_weapon_temp += weapon_shot_temperature;
forward_weapon_temp += weapon_shot_temperature * multiplier;
forward_shot_time = 0.0;
break;
case WEAPON_FACING_AFT:
aft_weapon_temp += weapon_shot_temperature;
aft_weapon_temp += weapon_shot_temperature * multiplier;
aft_shot_time = 0.0;
break;
case WEAPON_FACING_PORT:
port_weapon_temp += weapon_shot_temperature;
port_weapon_temp += weapon_shot_temperature * multiplier;
port_shot_time = 0.0;
break;
case WEAPON_FACING_STARBOARD:
starboard_weapon_temp += weapon_shot_temperature;
starboard_weapon_temp += weapon_shot_temperature * multiplier;
starboard_shot_time = 0.0;
break;

View File

@ -11403,7 +11403,14 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
}
if (weapon_temp / NPC_MAX_WEAPON_TEMP >= WEAPON_COOLING_CUTOUT) return NO;
if (energy <= weapon_energy_use) return NO;
NSUInteger multiplier = 1;
if (_multiplyWeapons)
{
// multiple fitted
multiplier = [[self laserPortOffset:direction] count];
}
if (energy <= weapon_energy_use * multiplier) return NO;
if ([self shotTime] < weapon_recharge_rate) return NO;
if (![weapon_type isTurretLaser])
{ // thargoid laser may just pick secondary target in this case
@ -11429,23 +11436,23 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
if (fired)
{
energy -= weapon_energy_use;
energy -= weapon_energy_use * multiplier;
switch (direction)
{
case WEAPON_FACING_FORWARD:
forward_weapon_temp += weapon_shot_temperature;
forward_weapon_temp += weapon_shot_temperature * multiplier;
break;
case WEAPON_FACING_AFT:
aft_weapon_temp += weapon_shot_temperature;
aft_weapon_temp += weapon_shot_temperature * multiplier;
break;
case WEAPON_FACING_PORT:
port_weapon_temp += weapon_shot_temperature;
port_weapon_temp += weapon_shot_temperature * multiplier;
break;
case WEAPON_FACING_STARBOARD:
starboard_weapon_temp += weapon_shot_temperature;
starboard_weapon_temp += weapon_shot_temperature * multiplier;
break;
case WEAPON_FACING_NONE:
@ -11860,92 +11867,110 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
{
double range_limit2 = weaponRange * weaponRange;
GLfloat hit_at_range;
NSUInteger i, barrels;
Vector vel = vector_multiply_scalar(v_forward, flightSpeed);
NSArray *laserPortOffsets = [self laserPortOffset:direction];
OOLaserShotEntity *shot = nil;
Vector laserPortOffset = [laserPortOffsets oo_vectorAtIndex:0];
last_shot_time = [UNIVERSE getTime];
barrels = [laserPortOffsets count];
ShipEntity *victim = [UNIVERSE firstShipHitByLaserFromShip:self inDirection:direction offset:laserPortOffset gettingRangeFound:&hit_at_range];
[self setShipHitByLaser:victim];
OOLaserShotEntity *shot = [OOLaserShotEntity laserFromShip:self direction:direction offset:laserPortOffset];
[shot setColor:laser_color];
[shot setScanClass: CLASS_NO_DRAW];
[shot setVelocity: vel];
if (victim != nil)
GLfloat effective_damage = weapon_damage;
if (barrels > 1 && !_multiplyWeapons)
{
[self adjustMissedShots:-1];
if ([self isPlayer])
{
[PLAYER addRoleForAggression:victim];
}
/* CRASH in [victim->sub_entities containsObject:subent] here (1.69, OS X/x86).
Analysis: Crash is in _freedHandler called from CFEqual, indicating either a dead
object in victim->sub_entities or dead victim->subentity_taking_damage. I suspect
the latter. Probable solution: dying subentities must cause parent to clean up
properly. This was probably obscured by the entity recycling scheme in the past.
Fix: made subentity_taking_damage a weak reference accessed via a method.
-- Ahruman 20070706, 20080304
*/
ShipEntity *subent = [victim subEntityTakingDamage];
if (subent != nil && [victim isFrangible])
{
// do 1% bleed-through damage...
[victim takeEnergyDamage: 0.01 * weapon_damage from:self becauseOf:self];
victim = subent;
}
if (hit_at_range * hit_at_range < range_limit2)
{
[victim takeEnergyDamage:weapon_damage from:self becauseOf:self]; // a very palpable hit
[shot setRange:hit_at_range];
Vector vd = vector_forward_from_quaternion([shot orientation]);
HPVector flash_pos = HPvector_add([shot position], vectorToHPVector(vector_multiply_scalar(vd, hit_at_range)));
[UNIVERSE addLaserHitEffectsAt:flash_pos against:victim damage:weapon_damage color:laser_color];
}
// then divide the shot power between the shots
effective_damage /= (GLfloat)barrels;
}
else
for (i=0;i<barrels;i++)
{
[self adjustMissedShots:+1];
Vector laserPortOffset = [laserPortOffsets oo_vectorAtIndex:i];
last_shot_time = [UNIVERSE getTime];
// shot missed
if (![self isCloaked])
ShipEntity *victim = [UNIVERSE firstShipHitByLaserFromShip:self inDirection:direction offset:laserPortOffset gettingRangeFound:&hit_at_range];
[self setShipHitByLaser:victim];
shot = [OOLaserShotEntity laserFromShip:self direction:direction offset:laserPortOffset];
[shot setColor:laser_color];
[shot setScanClass: CLASS_NO_DRAW];
[shot setVelocity: vel];
if (victim != nil)
{
victim = [self primaryTarget];
if ([victim isShip]) // it might not be - fixes crash bug
[self adjustMissedShots:-1];
if ([self isPlayer])
{
[PLAYER addRoleForAggression:victim];
}
/* CRASH in [victim->sub_entities containsObject:subent] here (1.69, OS X/x86).
Analysis: Crash is in _freedHandler called from CFEqual, indicating either a dead
object in victim->sub_entities or dead victim->subentity_taking_damage. I suspect
the latter. Probable solution: dying subentities must cause parent to clean up
properly. This was probably obscured by the entity recycling scheme in the past.
Fix: made subentity_taking_damage a weak reference accessed via a method.
-- Ahruman 20070706, 20080304
*/
ShipEntity *subent = [victim subEntityTakingDamage];
if (subent != nil && [victim isFrangible])
{
// do 1% bleed-through damage...
[victim takeEnergyDamage: 0.01 * effective_damage from:self becauseOf:self];
victim = subent;
}
if (hit_at_range * hit_at_range < range_limit2)
{
[victim takeEnergyDamage:effective_damage from:self becauseOf:self]; // a very palpable hit
/* player currently gets a bit of an advantage here if they ambush
* without having their target actually targeted. Though in those
* circumstances they shouldn't be missing their first shot
* anyway. */
if (dot_product(vector_forward_from_quaternion([shot orientation]),vector_normal([self vectorTo:victim])) > 0.995)
[shot setRange:hit_at_range];
Vector vd = vector_forward_from_quaternion([shot orientation]);
HPVector flash_pos = HPvector_add([shot position], vectorToHPVector(vector_multiply_scalar(vd, hit_at_range)));
[UNIVERSE addLaserHitEffectsAt:flash_pos against:victim damage:effective_damage color:laser_color];
}
}
else
{
[self adjustMissedShots:+1];
// shot missed
if (![self isCloaked])
{
victim = [self primaryTarget];
if ([victim isShip]) // it might not be - fixes crash bug
{
/* plausibly aimed at target. Allows reaction before attacker
* actually hits. But we need to be able to distinguish in AI
* from ATTACKED so that ships in combat aren't bothered by
* amateurs. So should only respond to ATTACKER_MISSED if not
* already fighting */
if ([self isPlayer])
/* player currently gets a bit of an advantage here if
* they ambush without having their target actually
* targeted. Though in those circumstances they
* shouldn't be missing their first shot anyway. */
if (dot_product(vector_forward_from_quaternion([shot orientation]),vector_normal([self vectorTo:victim])) > 0.995)
{
[PLAYER addRoleForAggression:victim];
/* plausibly aimed at target. Allows reaction
* before attacker actually hits. But we need to
* be able to distinguish in AI from ATTACKED so
* that ships in combat aren't bothered by
* amateurs. So should only respond to
* ATTACKER_MISSED if not already fighting */
if ([self isPlayer])
{
[PLAYER addRoleForAggression:victim];
}
[victim setPrimaryAggressor:self];
[victim setFoundTarget:self];
[victim reactToAIMessage:@"ATTACKER_MISSED" context:@"attacker narrowly misses"];
[victim doScriptEvent:OOJSID("shipBeingAttackedUnsuccessfully") withArgument:self];
}
[victim setPrimaryAggressor:self];
[victim setFoundTarget:self];
[victim reactToAIMessage:@"ATTACKER_MISSED" context:@"attacker narrowly misses"];
[victim doScriptEvent:OOJSID("shipBeingAttackedUnsuccessfully") withArgument:self];
}
}
}
[UNIVERSE addEntity:shot];
}
[UNIVERSE addEntity:shot];
if ([self isPlayer])
{
[(PlayerEntity *)self setLastShot:shot];