Allow exemption of ships from collision with each other
S.addCollisionException(ship) S.removeCollisionException(ship) S.collisionExceptions
This commit is contained in:
parent
7d1323ab68
commit
c7ceba26e6
@ -316,91 +316,101 @@ static BOOL positionIsWithinBorders(HPVector position, CollisionRegion *region)
|
||||
e1 = entities_to_test[i];
|
||||
p1 = e1->position;
|
||||
r1 = e1->collision_radius;
|
||||
|
||||
|
||||
|
||||
|
||||
// check against the first in the collision chain
|
||||
e2 = e1->collision_chain;
|
||||
while (e2 != nil)
|
||||
{
|
||||
checks_this_tick++;
|
||||
|
||||
r2 = e2->collision_radius;
|
||||
r0 = r1 + r2;
|
||||
dist2 = HPdistance2(e2->position, p1);
|
||||
min_dist2 = r0 * r0;
|
||||
if (dist2 < PROXIMITY_WARN_DISTANCE2 * min_dist2)
|
||||
if (e1->isShip && e2->isShip &&
|
||||
[(ShipEntity *)e1 collisionExceptedFor:(ShipEntity *)e2])
|
||||
{
|
||||
OOLog(@"collision.except",@"ignoring potential collision between %@ and %@",e1,e2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
r2 = e2->collision_radius;
|
||||
r0 = r1 + r2;
|
||||
dist2 = HPdistance2(e2->position, p1);
|
||||
min_dist2 = r0 * r0;
|
||||
if (dist2 < PROXIMITY_WARN_DISTANCE2 * min_dist2)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (gDebugFlags & DEBUG_COLLISIONS)
|
||||
{
|
||||
OOLog(@"collisionRegion.debug", @"DEBUG Testing collision between %@ (%@) and %@ (%@)",
|
||||
e1, (e1->collisionTestFilter==3)?@"YES":@"NO", e2, (e2->collisionTestFilter==3)?@"YES":@"NO");
|
||||
}
|
||||
#endif
|
||||
checks_within_range++;
|
||||
|
||||
if (e1->isShip && e2->isShip)
|
||||
{
|
||||
if ((dist2 < PROXIMITY_WARN_DISTANCE2 * r2 * r2) || (dist2 < PROXIMITY_WARN_DISTANCE2 * r1 * r1))
|
||||
if (gDebugFlags & DEBUG_COLLISIONS)
|
||||
{
|
||||
[(ShipEntity*)e1 setProximityAlert:(ShipEntity*)e2];
|
||||
[(ShipEntity*)e2 setProximityAlert:(ShipEntity*)e1];
|
||||
OOLog(@"collisionRegion.debug", @"DEBUG Testing collision between %@ (%@) and %@ (%@)",
|
||||
e1, (e1->collisionTestFilter==3)?@"YES":@"NO", e2, (e2->collisionTestFilter==3)?@"YES":@"NO");
|
||||
}
|
||||
}
|
||||
if (dist2 < min_dist2)
|
||||
{
|
||||
BOOL collision = NO;
|
||||
|
||||
if (e1->isStation)
|
||||
#endif
|
||||
checks_within_range++;
|
||||
|
||||
if (e1->isShip && e2->isShip)
|
||||
{
|
||||
StationEntity* se1 = (StationEntity *)e1;
|
||||
if ([se1 shipIsInDockingCorridor:(ShipEntity *)e2])
|
||||
if ((dist2 < PROXIMITY_WARN_DISTANCE2 * r2 * r2) || (dist2 < PROXIMITY_WARN_DISTANCE2 * r1 * r1))
|
||||
{
|
||||
collision = NO;
|
||||
[(ShipEntity*)e1 setProximityAlert:(ShipEntity*)e2];
|
||||
[(ShipEntity*)e2 setProximityAlert:(ShipEntity*)e1];
|
||||
}
|
||||
}
|
||||
if (dist2 < min_dist2)
|
||||
{
|
||||
BOOL collision = NO;
|
||||
|
||||
if (e1->isStation)
|
||||
{
|
||||
StationEntity* se1 = (StationEntity *)e1;
|
||||
if ([se1 shipIsInDockingCorridor:(ShipEntity *)e2])
|
||||
{
|
||||
collision = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
collision = [e1 checkCloseCollisionWith:e2];
|
||||
}
|
||||
}
|
||||
else if (e2->isStation)
|
||||
{
|
||||
StationEntity* se2 = (StationEntity *)e2;
|
||||
if ([se2 shipIsInDockingCorridor:(ShipEntity *)e1])
|
||||
{
|
||||
collision = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
collision = [e2 checkCloseCollisionWith:e1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
collision = [e1 checkCloseCollisionWith:e2];
|
||||
}
|
||||
}
|
||||
else if (e2->isStation)
|
||||
{
|
||||
StationEntity* se2 = (StationEntity *)e2;
|
||||
if ([se2 shipIsInDockingCorridor:(ShipEntity *)e1])
|
||||
{
|
||||
collision = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
collision = [e2 checkCloseCollisionWith:e1];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
collision = [e1 checkCloseCollisionWith:e2];
|
||||
}
|
||||
|
||||
if (collision)
|
||||
{
|
||||
// now we have no need to check the e2-e1 collision
|
||||
if (e1->collider)
|
||||
if (collision)
|
||||
{
|
||||
[[e1 collisionArray] addObject:e1->collider];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[e1 collisionArray] addObject:e2];
|
||||
}
|
||||
e1->hasCollided = YES;
|
||||
// now we have no need to check the e2-e1 collision
|
||||
if (e1->collider)
|
||||
{
|
||||
[[e1 collisionArray] addObject:e1->collider];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[e1 collisionArray] addObject:e2];
|
||||
}
|
||||
e1->hasCollided = YES;
|
||||
|
||||
if (e2->collider)
|
||||
{
|
||||
[[e2 collisionArray] addObject:e2->collider];
|
||||
if (e2->collider)
|
||||
{
|
||||
[[e2 collisionArray] addObject:e2->collider];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[e2 collisionArray] addObject:e1];
|
||||
}
|
||||
e2->hasCollided = YES;
|
||||
}
|
||||
else
|
||||
{
|
||||
[[e2 collisionArray] addObject:e1];
|
||||
}
|
||||
e2->hasCollided = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -461,6 +461,9 @@ typedef enum
|
||||
|
||||
OOWeakSet *_defenseTargets; // defense targets
|
||||
|
||||
// ships in this set can't be collided with
|
||||
OOWeakSet *_collisionExceptions;
|
||||
|
||||
GLfloat _profileRadius;
|
||||
|
||||
OOWeakReference *_shipHitByLaser; // entity hit by the last laser shot
|
||||
@ -783,6 +786,13 @@ typedef enum
|
||||
- (void) removeDefenseTarget:(Entity *)target;
|
||||
- (void) removeAllDefenseTargets;
|
||||
|
||||
// collision exceptions
|
||||
- (NSArray *) collisionExceptions;
|
||||
- (void) addCollisionException:(ShipEntity *)ship;
|
||||
- (void) removeCollisionException:(ShipEntity *)ship;
|
||||
- (BOOL) collisionExceptedFor:(ShipEntity *)ship;
|
||||
|
||||
|
||||
|
||||
- (GLfloat) weaponRange;
|
||||
- (void) setWeaponRange:(GLfloat) value;
|
||||
|
@ -1021,6 +1021,7 @@ static ShipEntity *doOctreesCollide(ShipEntity *prime, ShipEntity *other);
|
||||
DESTROY(lastRadioMessage);
|
||||
DESTROY(octree);
|
||||
DESTROY(_defenseTargets);
|
||||
DESTROY(_collisionExceptions);
|
||||
|
||||
DESTROY(commodity_type);
|
||||
|
||||
@ -10538,6 +10539,47 @@ Vector positionOffsetForShipInRotationToAlignment(ShipEntity* ship, Quaternion q
|
||||
}
|
||||
|
||||
|
||||
- (NSArray *) collisionExceptions
|
||||
{
|
||||
if (_collisionExceptions == nil)
|
||||
{
|
||||
return [NSArray array];
|
||||
}
|
||||
return [_collisionExceptions allObjects];
|
||||
}
|
||||
|
||||
|
||||
- (void) addCollisionException:(ShipEntity *)ship
|
||||
{
|
||||
if (_collisionExceptions == nil)
|
||||
{
|
||||
// Allocate lazily for the benefit of the ships that never need this.
|
||||
_collisionExceptions = [[OOWeakSet alloc] init];
|
||||
}
|
||||
[_collisionExceptions addObject:ship];
|
||||
}
|
||||
|
||||
|
||||
- (void) removeCollisionException:(ShipEntity *)ship
|
||||
{
|
||||
if (_collisionExceptions != nil)
|
||||
{
|
||||
[_collisionExceptions removeObject:ship];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (BOOL) collisionExceptedFor:(ShipEntity *)ship
|
||||
{
|
||||
if (_collisionExceptions == nil)
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
return [_collisionExceptions containsObject:ship];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (NSUInteger) defenseTargetCount
|
||||
{
|
||||
return [_defenseTargets count];
|
||||
|
@ -98,6 +98,8 @@ static JSBool ShipUpdateEscortFormation(JSContext *context, uintN argc, jsval *v
|
||||
static JSBool ShipClearDefenseTargets(JSContext *context, uintN argc, jsval *vp);
|
||||
static JSBool ShipAddDefenseTarget(JSContext *context, uintN argc, jsval *vp);
|
||||
static JSBool ShipRemoveDefenseTarget(JSContext *context, uintN argc, jsval *vp);
|
||||
static JSBool ShipAddCollisionException(JSContext *context, uintN argc, jsval *vp);
|
||||
static JSBool ShipRemoveCollisionException(JSContext *context, uintN argc, jsval *vp);
|
||||
static JSBool ShipGetMaterials(JSContext *context, uintN argc, jsval *vp);
|
||||
static JSBool ShipGetShaders(JSContext *context, uintN argc, jsval *vp);
|
||||
static JSBool ShipBecomeCascadeExplosion(JSContext *context, uintN argc, jsval *vp);
|
||||
@ -194,6 +196,7 @@ enum
|
||||
kShip_cargoSpaceAvailable, // free cargo space, integer, read-only
|
||||
kShip_cargoSpaceCapacity, // maximum cargo, integer, read-only
|
||||
kShip_cargoSpaceUsed, // cargo on board, integer, read-only
|
||||
kShip_collisionExceptions, // collision exception list, array, read-only
|
||||
kShip_contracts, // cargo contracts contracts, array - strings & whatnot, read only
|
||||
kShip_commodity, // commodity of a ship, read only
|
||||
kShip_commodityAmount, // commodityAmount of a ship, read only
|
||||
@ -336,6 +339,7 @@ static JSPropertySpec sShipProperties[] =
|
||||
{ "cargoSpaceUsed", kShip_cargoSpaceUsed, OOJS_PROP_READONLY_CB },
|
||||
{ "cargoSpaceCapacity", kShip_cargoSpaceCapacity, OOJS_PROP_READONLY_CB },
|
||||
{ "cargoSpaceAvailable", kShip_cargoSpaceAvailable, OOJS_PROP_READONLY_CB },
|
||||
{ "collisionExceptions", kShip_collisionExceptions, OOJS_PROP_READONLY_CB },
|
||||
{ "commodity", kShip_commodity, OOJS_PROP_READONLY_CB },
|
||||
{ "commodityAmount", kShip_commodityAmount, OOJS_PROP_READONLY_CB },
|
||||
// contracts instead of cargo to distinguish them from the manifest
|
||||
@ -461,6 +465,7 @@ static JSFunctionSpec sShipMethods[] =
|
||||
{
|
||||
// JS name Function min args
|
||||
{ "abandonShip", ShipAbandonShip, 0 },
|
||||
{ "addCollisionException", ShipAddCollisionException, 1 },
|
||||
{ "addDefenseTarget", ShipAddDefenseTarget, 1 },
|
||||
{ "awardEquipment", ShipAwardEquipment, 1 },
|
||||
{ "becomeCascadeExplosion", ShipBecomeCascadeExplosion, 0 },
|
||||
@ -512,6 +517,7 @@ static JSFunctionSpec sShipMethods[] =
|
||||
|
||||
{ "reactToAIMessage", ShipReactToAIMessage, 1 },
|
||||
{ "remove", ShipRemove, 0 },
|
||||
{ "removeCollisionException", ShipRemoveCollisionException, 1 },
|
||||
{ "removeDefenseTarget", ShipRemoveDefenseTarget, 1 },
|
||||
{ "removeEquipment", ShipRemoveEquipment, 1 },
|
||||
{ "requestHelpFromGroup", ShipRequestHelpFromGroup, 0},
|
||||
@ -832,6 +838,11 @@ static JSBool ShipGetProperty(JSContext *context, JSObject *this, jsid propID, j
|
||||
case kShip_commodityAmount:
|
||||
*value = INT_TO_JSVAL([entity commodityAmount]);
|
||||
return YES;
|
||||
|
||||
case kShip_collisionExceptions:
|
||||
result = [entity collisionExceptions];
|
||||
break;
|
||||
|
||||
|
||||
case kShip_speed:
|
||||
return JS_NewNumberValue(context, [entity flightSpeed], value);
|
||||
@ -3155,6 +3166,56 @@ static JSBool ShipRemoveDefenseTarget(JSContext *context, uintN argc, jsval *vp)
|
||||
}
|
||||
|
||||
|
||||
static JSBool ShipAddCollisionException(JSContext *context, uintN argc, jsval *vp)
|
||||
{
|
||||
OOJS_PROFILE_ENTER
|
||||
|
||||
ShipEntity *thisEnt = nil;
|
||||
ShipEntity *target = nil;
|
||||
|
||||
GET_THIS_SHIP(thisEnt);
|
||||
if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
|
||||
{
|
||||
OOJSReportBadArguments(context, @"Ship", @"addCollisionException", 1U, OOJS_ARGV, nil, @"other ship");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// have to do it both ways because it's not defined which order
|
||||
// the collisions get tested in. More efficient to add both ways
|
||||
// than to test both ways
|
||||
[thisEnt addCollisionException:target];
|
||||
[target addCollisionException:thisEnt];
|
||||
|
||||
OOJS_RETURN_VOID;
|
||||
|
||||
OOJS_PROFILE_EXIT
|
||||
}
|
||||
|
||||
|
||||
static JSBool ShipRemoveCollisionException(JSContext *context, uintN argc, jsval *vp)
|
||||
{
|
||||
OOJS_PROFILE_ENTER
|
||||
|
||||
ShipEntity *thisEnt = nil;
|
||||
ShipEntity *target = nil;
|
||||
|
||||
GET_THIS_SHIP(thisEnt);
|
||||
if (EXPECT_NOT(argc == 0 || (argc > 0 && (JSVAL_IS_NULL(OOJS_ARGV[0]) || !JSVAL_IS_OBJECT(OOJS_ARGV[0]) || !JSShipGetShipEntity(context, JSVAL_TO_OBJECT(OOJS_ARGV[0]), &target)))))
|
||||
{
|
||||
OOJSReportBadArguments(context, @"Ship", @"removeCollisionException", 1U, OOJS_ARGV, nil, @"other ship");
|
||||
return NO;
|
||||
}
|
||||
|
||||
// doesn't need a check to see if it was already gone
|
||||
[thisEnt removeCollisionException:target];
|
||||
[target removeCollisionException:thisEnt];
|
||||
|
||||
OOJS_RETURN_VOID;
|
||||
|
||||
OOJS_PROFILE_EXIT
|
||||
}
|
||||
|
||||
|
||||
//getMaterials()
|
||||
static JSBool ShipGetMaterials(JSContext *context, uintN argc, jsval *vp)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user