Skip to content

Commit d7fb4c4

Browse files
authored
Merge pull request #84 from Andreas-W/genpower_ocl_stuff
Genpower ocl stuff
2 parents 7c9800e + 11dca1f commit d7fb4c4

7 files changed

Lines changed: 208 additions & 17 deletions

File tree

GeneralsMD/Code/GameEngine/Include/GameLogic/Module/DeliverPayloadAIUpdate.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,9 @@ class DeliverPayloadData
254254
Coord3D m_dropVariance;
255255
UnsignedInt m_dropDelay;
256256
Bool m_fireWeapon;
257+
258+
UnsignedInt m_fireWeaponSlots;
259+
257260
Bool m_selfDestructObject;
258261
Int m_visibleNumBones; ///< The number of visible bones to process.
259262
Real m_diveStartDistance;
@@ -278,6 +281,7 @@ class DeliverPayloadData
278281
m_dropVariance.zero();
279282
m_dropDelay = 0;
280283
m_fireWeapon = false;
284+
m_fireWeaponSlots = 1u << PRIMARY_WEAPON;
281285
m_visibleNumBones = 0;
282286
m_diveStartDistance = 0.0f;
283287
m_diveEndDistance = 0.0f;
@@ -326,14 +330,15 @@ class DeliverPayloadAIUpdate : public AIUpdateInterface
326330
const Coord3D& getDropOffset() const { return m_data.m_dropOffset; }
327331
const Coord3D& getDropVariance() const { return m_data.m_dropVariance; }
328332
Bool isFireWeapon() const { return m_data.m_fireWeapon; }
333+
Bool shouldFireWeaponSlot(WeaponSlotType wslot) const { return (m_data.m_fireWeaponSlots & (1 << wslot)) != 0; }
329334
Int getVisibleItemsDelivered() const { return m_visibleItemsDelivered; }
330335
void setVisibleItemsDelivered( Int num ) { m_visibleItemsDelivered = num; }
331336

332337
Bool isCloseEnoughToTarget();
333338
Bool isOffMap() const;
334339
Real calcMinTurnRadius(Real* timeToTravelThatDist) const;
335340

336-
void deliverPayload( const Coord3D *moveToPos, const Coord3D *targetPos, const DeliverPayloadData *data );
341+
void deliverPayload( const Coord3D *moveToPos, const Coord3D *targetPos, const DeliverPayloadData *data, const Coord3D *decalOffset = nullptr );
337342
void deliverPayloadViaModuleData( const Coord3D *moveToPos );
338343

339344
const DeliverPayloadData* getData() { return &m_data; }

GeneralsMD/Code/GameEngine/Include/GameLogic/Module/OCLUpdate.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class OCLUpdateModuleData : public UpdateModuleData
5454
Bool m_isCreateAtEdge; ///< Otherwise, it is created on top of myself
5555
Bool m_isFactionTriggered; ///< Faction has to be present before update will happen
5656

57+
Bool m_isDirectionalDelivery; ///< Deliver payload aligned to source object
58+
Bool m_isDirectionalDeliveryFurthestEdge; ///< always get the furthest edge matching angle
59+
5760
OCLUpdateModuleData();
5861

5962
static void buildFieldParse(MultiIniFieldParse& p);

GeneralsMD/Code/GameEngine/Include/GameLogic/TerrainLogic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@ class TerrainLogic : public Snapshot,
234234
virtual void getMaximumPathfindExtent( Region3D *extent ) const { DEBUG_CRASH(("not implemented")); } ///< @todo This should not be a stub - this should own this functionality
235235
virtual Coord3D findClosestEdgePoint( const Coord3D *closestTo ) const ;
236236
virtual Coord3D findFarthestEdgePoint( const Coord3D *farthestFrom ) const ;
237+
238+
virtual Coord3D findEdgePointForAngle(const Coord3D* pos, Real angle, bool farthest = FALSE, bool closest = FALSE) const;
239+
240+
237241
virtual Bool isClearLineOfSight(const Coord3D& pos, const Coord3D& posOther) const;
238242

239243
virtual AsciiString getSourceFilename( void ) { return m_filenameString; }

GeneralsMD/Code/GameEngine/Source/GameLogic/Map/TerrainLogic.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,7 +2169,117 @@ Coord3D TerrainLogic::findFarthestEdgePoint( const Coord3D *farthestFrom ) const
21692169
}
21702170

21712171

2172+
//-------------------------------------------------------------------------------------------------
2173+
/** Returns the ground aligned point on the bounding box closest to the given point*/
2174+
//-------------------------------------------------------------------------------------------------
2175+
Coord3D TerrainLogic::findEdgePointForAngle(const Coord3D* pos, Real angle, bool farthest/* = FALSE*/, bool closest/* = FALSE*/) const
2176+
{
2177+
Region3D mapExtent;
2178+
getExtent(&mapExtent);
2179+
2180+
// Map bounds (XY only)
2181+
const Real minX = mapExtent.lo.x;
2182+
const Real minY = mapExtent.lo.y;
2183+
const Real maxX = mapExtent.hi.x;
2184+
const Real maxY = mapExtent.hi.y;
2185+
2186+
const Real x0 = pos->x;
2187+
const Real y0 = pos->y;
2188+
2189+
// Direction from angle
2190+
const Real dx = std::cos(angle);
2191+
const Real dy = std::sin(angle);
2192+
2193+
// Small epsilon for float comparisons
2194+
const Real eps = static_cast<Real>(1e-6);
2195+
2196+
struct Hit
2197+
{
2198+
Real t;
2199+
Real x;
2200+
Real y;
2201+
};
2202+
2203+
Hit hits[4];
2204+
int hitCount = 0;
2205+
2206+
auto addHit = [&](Real t)
2207+
{
2208+
if (t < 0) return; // only forward along the ray
2209+
2210+
const Real x = x0 + t * dx;
2211+
const Real y = y0 + t * dy;
2212+
2213+
// Keep only points that lie on the rectangle boundary
2214+
if (x >= minX - eps && x <= maxX + eps &&
2215+
y >= minY - eps && y <= maxY + eps)
2216+
{
2217+
// Avoid duplicates (corner hits can be found twice)
2218+
for (int i = 0; i < hitCount; ++i)
2219+
{
2220+
if (std::abs(hits[i].x - x) < eps &&
2221+
std::abs(hits[i].y - y) < eps)
2222+
{
2223+
return;
2224+
}
2225+
}
2226+
2227+
hits[hitCount++] = { t, x, y };
2228+
}
2229+
};
2230+
2231+
// Intersect ray P(t) = (x0,y0) + t(dx,dy), t >= 0
2232+
// with the 4 rectangle edges
2233+
2234+
// x = minX
2235+
if (std::abs(dx) > eps)
2236+
addHit((minX - x0) / dx);
2237+
2238+
// x = maxX
2239+
if (std::abs(dx) > eps)
2240+
addHit((maxX - x0) / dx);
2241+
2242+
// y = minY
2243+
if (std::abs(dy) > eps)
2244+
addHit((minY - y0) / dy);
2245+
2246+
// y = maxY
2247+
if (std::abs(dy) > eps)
2248+
addHit((maxY - y0) / dy);
2249+
2250+
// No hit should only happen if pos is invalid or outside map
2251+
if (hitCount == 0)
2252+
return *pos;
2253+
2254+
// Default behavior:
2255+
// - if closest == true -> nearest hit
2256+
// - if farthest == true -> farthest hit
2257+
// - otherwise -> nearest forward hit
2258+
int best = 0;
21722259

2260+
if (farthest)
2261+
{
2262+
for (int i = 1; i < hitCount; ++i)
2263+
{
2264+
if (hits[i].t > hits[best].t)
2265+
best = i;
2266+
}
2267+
}
2268+
else // closest or default
2269+
{
2270+
for (int i = 1; i < hitCount; ++i)
2271+
{
2272+
if (hits[i].t < hits[best].t)
2273+
best = i;
2274+
}
2275+
}
2276+
2277+
Coord3D result = *pos;
2278+
result.x = hits[best].x;
2279+
result.y = hits[best].y;
2280+
// preserve original Z (XY only matters)
2281+
return result;
2282+
}
21732283

21742284

21752285
//-------------------------------------------------------------------------------------------------

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ class DeliverPayloadNugget : public ObjectCreationNugget
259259
m_payload.clear();
260260
m_putInContainerName.clear();
261261
m_transportName.clear();
262+
m_targetOffset = { 0.0, 0.0 };
262263
}
263264

264265
virtual Object* create(const Object *primaryObj, const Coord3D *primary, const Coord3D *secondary, Real angle, UnsignedInt lifetimeFrames = 0 ) const
@@ -283,7 +284,9 @@ class DeliverPayloadNugget : public ObjectCreationNugget
283284
//resultant vectors to the initial vectors, we can calculate the delta positions for each plane.
284285
Real CCWx = 0.0f, CCWy = 0.0f, CWx = 0.0f, CWy = 0.0f;
285286

286-
if( m_formationSize > 1 )
287+
Real targetOffsetX = 0.0f, targetOffsetY = 0.0f;
288+
289+
if (m_formationSize > 1 || m_targetOffset.x != 0.0f || m_targetOffset.y != 0.0f)
287290
{
288291
//Get the delta x and y values from the target to the origin.
289292
Real dx = primary->x - secondary->x;
@@ -296,16 +299,19 @@ class DeliverPayloadNugget : public ObjectCreationNugget
296299
dx /= length;
297300
dy /= length;
298301

302+
targetOffsetX = dx * m_targetOffset.x - dy * m_targetOffset.y;
303+
targetOffsetY = dy * m_targetOffset.x + dx * m_targetOffset.y;
304+
299305
//Rotate 90 degrees CCW.
300306
Real radians = 90.0f * PI / 180.0f;
301-
Real s = Sin( radians );
302-
Real c = Cos( radians );
307+
Real s = Sin(radians);
308+
Real c = Cos(radians);
303309
CCWx = dx * c + dy * -s + dx;
304310
CCWy = dx * s + dy * c + dy;
305311

306312
//Rotate 90 degrees CW
307-
s = Sin( -radians );
308-
c = Cos( -radians );
313+
s = Sin(-radians);
314+
c = Cos(-radians);
309315
CWx = dx * c + dy * -s + dx;
310316
CWy = dx * s + dy * c + dy;
311317
}
@@ -331,6 +337,9 @@ class DeliverPayloadNugget : public ObjectCreationNugget
331337
offset.y = CWy * offsetMultiplier;
332338
}
333339

340+
offset.x += targetOffsetX;
341+
offset.y += targetOffsetY;
342+
334343
Coord3D startPos = *primary;
335344
Coord3D moveToPos = *secondary;
336345
startPos.add( &offset );
@@ -407,9 +416,9 @@ class DeliverPayloadNugget : public ObjectCreationNugget
407416

408417
static NameKeyType key_DeliverPayloadAIUpdate = NAMEKEY("DeliverPayloadAIUpdate");
409418
DeliverPayloadAIUpdate *ai = (DeliverPayloadAIUpdate*)transport->findUpdateModule(key_DeliverPayloadAIUpdate);
410-
if( ai )
419+
if (ai)
411420
{
412-
if( m_startAtMaxSpeed && createOwner )
421+
if (m_startAtMaxSpeed && createOwner)
413422
{
414423
PhysicsBehavior* physics = transport->getPhysics();
415424
if (physics)
@@ -420,15 +429,24 @@ class DeliverPayloadNugget : public ObjectCreationNugget
420429
startingForce.x *= factor;
421430
startingForce.y *= factor;
422431
startingForce.z *= factor;
423-
physics->applyMotiveForce( &startingForce );
432+
physics->applyMotiveForce(&startingForce);
424433
}
425434
}
426435

427436
// only the first guy in each formation gets a delivery decal
428437
DeliverPayloadData data = m_data;
429-
if (formationIndex != 0)
438+
if (formationIndex != 0) {
430439
data.m_deliveryDecalRadius = 0;
431-
ai->deliverPayload( &moveToPos, &targetPos, &data );
440+
}
441+
442+
if (targetOffsetX != 0.0 || targetOffsetY != 0.0) {
443+
Coord3D decalOffset = { -targetOffsetX, -targetOffsetY };
444+
ai->deliverPayload(&moveToPos, &targetPos, &data, &decalOffset);
445+
}
446+
else {
447+
ai->deliverPayload(&moveToPos, &targetPos, &data);
448+
}
449+
432450
if( m_startAtPreferredHeight && createOwner )
433451
{
434452
startPos.z = TheTerrainLogic->getGroundHeight(startPos.x, startPos.y) + ai->getCurLocomotor()->getPreferredHeight();
@@ -538,6 +556,8 @@ class DeliverPayloadNugget : public ObjectCreationNugget
538556
{ "WeaponErrorRadius", INI::parseReal, nullptr, offsetof( DeliverPayloadNugget, m_errorRadius ) },
539557
{ "DelayDeliveryMax", INI::parseDurationUnsignedInt, nullptr, offsetof( DeliverPayloadNugget, m_delayDeliveryFramesMax ) },
540558

559+
{ "TargetOffset", INI::parseCoord2D, nullptr, offsetof( DeliverPayloadNugget, m_targetOffset ) },
560+
541561
//Payload information (it's all created now and stored inside)
542562
{ "Payload", parsePayload, nullptr, 0 },
543563
{ "PutInContainer", INI::parseAsciiString, nullptr, offsetof( DeliverPayloadNugget, m_putInContainerName) },
@@ -579,6 +599,8 @@ class DeliverPayloadNugget : public ObjectCreationNugget
579599
Bool m_startAtPreferredHeight;
580600
Bool m_startAtMaxSpeed;
581601

602+
Coord2D m_targetOffset;
603+
582604
//AI specific data passed over to DeliverPayloadAIUpdate::deliver()
583605
DeliverPayloadData m_data;
584606
};

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/DeliverPayloadAIUpdate.cpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@
5252

5353

5454
//-------------------------------------------------------------------------------------------------
55+
// duplicate from TurretAI
56+
static void parseTWS(INI* ini, void* /*instance*/, void* store, const void* /*userData*/)
57+
{
58+
UnsignedInt* tws = (UnsignedInt*)store;
59+
const char* token = ini->getNextToken();
60+
while (token != nullptr)
61+
{
62+
WeaponSlotType wslot = (WeaponSlotType)INI::scanIndexList(token, TheWeaponSlotTypeNames);
63+
*tws |= (1 << wslot);
64+
token = ini->getNextTokenOrNull();
65+
}
66+
}
67+
// ---
68+
5569
const FieldParse* DeliverPayloadData::getFieldParse()
5670
{
5771
static const FieldParse dataFieldParse[] =
@@ -80,6 +94,7 @@ const FieldParse* DeliverPayloadData::getFieldParse()
8094

8195
//Weapon based payload
8296
{ "FireWeapon", INI::parseBool, nullptr, offsetof( DeliverPayloadData, m_fireWeapon ) },
97+
{ "FireWeaponSlots", parseTWS, nullptr, offsetof(DeliverPayloadData, m_fireWeaponSlots) },
8398

8499
//Specify an additional weaponslot to be fired while strafing
85100
{ "DiveStartDistance", INI::parseReal, nullptr, offsetof( DeliverPayloadData, m_diveStartDistance ) },
@@ -239,7 +254,8 @@ UpdateSleepTime DeliverPayloadAIUpdate::update( void )
239254
void DeliverPayloadAIUpdate::deliverPayload(
240255
const Coord3D *moveToPos,
241256
const Coord3D *targetPos,
242-
const DeliverPayloadData *data
257+
const DeliverPayloadData *data,
258+
const Coord3D *decalOffset /* = NULL*/
243259
)
244260
{
245261

@@ -255,8 +271,18 @@ void DeliverPayloadAIUpdate::deliverPayload(
255271
m_data = *data;
256272

257273
m_deliveryDecal.clear();
258-
m_data.m_deliveryDecalTemplate.createRadiusDecal(*targetPos,
259-
m_data.m_deliveryDecalRadius, getObject()->getControllingPlayer(), m_deliveryDecal);
274+
275+
if (decalOffset != nullptr) {
276+
Coord3D decalPos = *targetPos;
277+
decalPos.add(decalOffset);
278+
m_data.m_deliveryDecalTemplate.createRadiusDecal(decalPos,
279+
m_data.m_deliveryDecalRadius, getObject()->getControllingPlayer(), m_deliveryDecal);
280+
}
281+
else {
282+
m_data.m_deliveryDecalTemplate.createRadiusDecal(*targetPos,
283+
m_data.m_deliveryDecalRadius, getObject()->getControllingPlayer(), m_deliveryDecal);
284+
}
285+
260286

261287
if( m_data.m_diveStartDistance <= 0.0f )
262288
{
@@ -434,6 +460,7 @@ void DeliverPayloadAIUpdate::xfer( Xfer *xfer )
434460
xfer->xferCoord3D(&data.m_dropVariance);
435461
xfer->xferUnsignedInt(&data.m_dropDelay);
436462
xfer->xferBool(&data.m_fireWeapon);
463+
xfer->xferUnsignedInt(&data.m_fireWeaponSlots);
437464
xfer->xferBool(&data.m_selfDestructObject);
438465
xfer->xferInt(&data.m_visibleNumBones);
439466
xfer->xferReal(&data.m_diveStartDistance);
@@ -715,7 +742,17 @@ StateReturnType DeliveringState::update() // Kick a dude out every so often
715742
pos.x += ai->getDropOffset().x;
716743
pos.y += ai->getDropOffset().y;
717744
pos.z += ai->getDropOffset().z;
718-
owner->fireCurrentWeapon( &pos );
745+
746+
for (int i = 0; i < WEAPONSLOT_COUNT; i++) {
747+
WeaponSlotType wslot = (WeaponSlotType)i;
748+
if (ai->shouldFireWeaponSlot(wslot)) {
749+
owner->setWeaponLock(wslot, LOCKED_TEMPORARILY);
750+
owner->fireCurrentWeapon(&pos);
751+
}
752+
}
753+
//owner->fireCurrentWeapon( &pos );
754+
755+
719756
TheGameLogic->destroyObject( item );
720757
}
721758
else

0 commit comments

Comments
 (0)