mirror of
https://github.com/cxong/cdogs-sdl.git
synced 2025-07-23 07:23:01 +02:00
Add rocket launcher (#268)
Change Friction to a single number Enable Elevation JSON property for weapons Enable multiple collisions for bullets
This commit is contained in:
52
bullets.json
52
bullets.json
@@ -232,7 +232,7 @@
|
||||
"Tint": [120.0, 0.33, 2.0]
|
||||
},
|
||||
"Speed": 384,
|
||||
"Friction": [4, 3],
|
||||
"Friction": 4,
|
||||
"Range": 35,
|
||||
"Size": [10, 10],
|
||||
"Special": "Poison",
|
||||
@@ -455,7 +455,7 @@
|
||||
"SpeedLow": -256,
|
||||
"SpeedHigh": 256,
|
||||
"SpeedScale": true,
|
||||
"Friction": [4, 3],
|
||||
"Friction": 4,
|
||||
"RangeLow": 120,
|
||||
"RangeHigh": 148,
|
||||
"Power": 2,
|
||||
@@ -484,7 +484,7 @@
|
||||
},
|
||||
"SpeedLow": 0,
|
||||
"SpeedHigh": 255,
|
||||
"Friction": [4, 3],
|
||||
"Friction": 4,
|
||||
"RangeLow": 155,
|
||||
"RangeHigh": 191,
|
||||
"Size": [10, 10],
|
||||
@@ -509,7 +509,7 @@
|
||||
},
|
||||
"SpeedLow": 0,
|
||||
"SpeedHigh": 255,
|
||||
"Friction": [4, 3],
|
||||
"Friction": 4,
|
||||
"RangeLow": 155,
|
||||
"RangeHigh": 191,
|
||||
"Size": [10, 10],
|
||||
@@ -552,6 +552,50 @@
|
||||
"explosion2",
|
||||
"explosion3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "explosion_small",
|
||||
"Pic": {
|
||||
"Type": "Animated",
|
||||
"Sprites": "explosion_small",
|
||||
"TicksPerFrame": 4
|
||||
},
|
||||
"Speed": 0,
|
||||
"Range": 27,
|
||||
"Power": 3,
|
||||
"Size": [32, 32],
|
||||
"Persists": true,
|
||||
"Spark": "",
|
||||
"HitSounds": {
|
||||
"Object": "hit_gas",
|
||||
"Flesh": "hit_gas",
|
||||
"Wall": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "rocket",
|
||||
"Pic": {
|
||||
"Type": "Directional",
|
||||
"Sprites": "rocket_blue"
|
||||
},
|
||||
"ShadowSize": [2, 2],
|
||||
"Speed": 250,
|
||||
"Friction": -9,
|
||||
"Range": 120,
|
||||
"Power": 1,
|
||||
"Size": [8, 8],
|
||||
"Spark": "",
|
||||
"HitSounds": {
|
||||
"Object": "",
|
||||
"Flesh": "",
|
||||
"Wall": ""
|
||||
},
|
||||
"OutOfRangeGuns": [
|
||||
"explosion_small"
|
||||
],
|
||||
"HitGuns": [
|
||||
"explosion_small"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
BIN
graphics/explosion_small_34x34.png
Normal file
BIN
graphics/explosion_small_34x34.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
5
graphics/explosion_small_34x34.txt
Normal file
5
graphics/explosion_small_34x34.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Adapted from Explosion Set 1 (M484 Games)
|
||||
By Master484
|
||||
http://opengameart.org/content/explosion-set-1-m484-games
|
||||
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
BIN
graphics/rocket_blue_12x12.png
Normal file
BIN
graphics/rocket_blue_12x12.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
45
guns.json
45
guns.json
@@ -48,8 +48,7 @@
|
||||
"Cost": 20,
|
||||
"Lock": 30,
|
||||
"Sound": "launch",
|
||||
"ElevationLow": 24,
|
||||
"ElevationHigh": 24
|
||||
"Elevation": 24
|
||||
},
|
||||
{
|
||||
"Index": 3,
|
||||
@@ -92,8 +91,7 @@
|
||||
"Cost": 20,
|
||||
"Lock": 30,
|
||||
"Sound": "launch",
|
||||
"ElevationLow": 24,
|
||||
"ElevationHigh": 24
|
||||
"Elevation": 24
|
||||
},
|
||||
{
|
||||
"Index": 7,
|
||||
@@ -103,8 +101,7 @@
|
||||
"Cost": 20,
|
||||
"Lock": 30,
|
||||
"Sound": "launch",
|
||||
"ElevationLow": 24,
|
||||
"ElevationHigh": 24
|
||||
"Elevation": 24
|
||||
},
|
||||
{
|
||||
"Index": 8,
|
||||
@@ -151,8 +148,7 @@
|
||||
"Cost": 7,
|
||||
"Lock": 30,
|
||||
"Sound": "launch",
|
||||
"ElevationLow": 24,
|
||||
"ElevationHigh": 24
|
||||
"Elevation": 24
|
||||
},
|
||||
{
|
||||
"Index": 12,
|
||||
@@ -182,8 +178,7 @@
|
||||
"Cost": 10,
|
||||
"Lock": 30,
|
||||
"Sound": "launch",
|
||||
"ElevationLow": 24,
|
||||
"ElevationHigh": 24
|
||||
"Elevation": 24
|
||||
},
|
||||
{
|
||||
"Index": 15,
|
||||
@@ -224,6 +219,23 @@
|
||||
"SpreadWidth": 0.4,
|
||||
"Sound": "swarmer",
|
||||
"MuzzleFlashParticle": "muzzle_flash_heatseeker"
|
||||
},
|
||||
{
|
||||
"Name": "Launcher",
|
||||
"Bullet": "rocket",
|
||||
"Cost": 15,
|
||||
"Lock": 70,
|
||||
"Sound": "rocket_launch",
|
||||
"Elevation": 25,
|
||||
"MuzzleFlashParticle": "muzzle_flash_shotgun"
|
||||
},
|
||||
{
|
||||
"Name": "Infinite Grenades",
|
||||
"Bullet": "infinite_grenade",
|
||||
"Cost": 0,
|
||||
"Lock": 1000,
|
||||
"Sound": "launch",
|
||||
"Elevation": 24
|
||||
}
|
||||
],
|
||||
"PseudoGuns" : [
|
||||
@@ -267,8 +279,8 @@
|
||||
"Sound": "",
|
||||
"SpreadCount": 8,
|
||||
"SpreadWidth": 0.79,
|
||||
"ElevationLow": 17,
|
||||
"ElevationHigh": 15
|
||||
"ElevationLow": 15,
|
||||
"ElevationHigh": 17
|
||||
},
|
||||
{
|
||||
"Pic": "",
|
||||
@@ -278,8 +290,7 @@
|
||||
"SpreadCount": 8,
|
||||
"SpreadWidth": 0.79,
|
||||
"AngleOffset": 0.39,
|
||||
"ElevationLow": 21,
|
||||
"ElevationHigh": 21
|
||||
"Elevation": 21
|
||||
},
|
||||
{
|
||||
"Pic": "",
|
||||
@@ -300,6 +311,12 @@
|
||||
"Name": "triggeredmine",
|
||||
"Bullet": "triggeredmine",
|
||||
"Sound": "mine_trigger"
|
||||
},
|
||||
{
|
||||
"Pic": "",
|
||||
"Name": "explosion_small",
|
||||
"Bullet": "explosion_small",
|
||||
"Sound": "explosion_small"
|
||||
}
|
||||
]
|
||||
}
|
@@ -102,6 +102,12 @@
|
||||
"Sprites": "smoke",
|
||||
"Range": 29,
|
||||
"TicksPerFrame": 6
|
||||
},
|
||||
{
|
||||
"Name": "explosion_small",
|
||||
"Sprites": "explosion_small",
|
||||
"Range": 7,
|
||||
"TicksPerFrame": 4
|
||||
}
|
||||
]
|
||||
}
|
4
sounds/explosion_small.txt
Normal file
4
sounds/explosion_small.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Derived from cannon_boom7.wav by ReadeOnly
|
||||
http://freesound.org/people/ReadeOnly/sounds/186951/
|
||||
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
BIN
sounds/explosion_small.wav
Normal file
BIN
sounds/explosion_small.wav
Normal file
Binary file not shown.
4
sounds/rocket_launch.txt
Normal file
4
sounds/rocket_launch.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
4 projectile launches by Michel Baradari
|
||||
http://opengameart.org/content/4-projectile-launches
|
||||
|
||||
http://creativecommons.org/licenses/by/3.0/
|
BIN
sounds/rocket_launch.wav
Normal file
BIN
sounds/rocket_launch.wav
Normal file
Binary file not shown.
@@ -191,7 +191,7 @@ bool UpdateBullet(TMobileObject *obj, const int ticks)
|
||||
}
|
||||
|
||||
Vec2i pos = Vec2iScale(Vec2iAdd(objPos, obj->vel), ticks);
|
||||
const bool hitItem = HitItem(obj, pos);
|
||||
const bool hitItem = HitItem(obj, pos, obj->bulletClass->Persists);
|
||||
const Vec2i realPos = Vec2iFull2Real(pos);
|
||||
|
||||
// Falling (grenades)
|
||||
@@ -239,24 +239,28 @@ bool UpdateBullet(TMobileObject *obj, const int ticks)
|
||||
}
|
||||
|
||||
// Friction
|
||||
const bool isDiagonal = obj->vel.x != 0 && obj->vel.y != 0;
|
||||
int frictionComponent = isDiagonal ?
|
||||
(int)round(obj->bulletClass->Friction / sqrt(2)) :
|
||||
obj->bulletClass->Friction;
|
||||
for (int i = 0; i < ticks; i++)
|
||||
{
|
||||
if (obj->vel.x > 0)
|
||||
{
|
||||
obj->vel.x -= obj->bulletClass->Friction.x;
|
||||
obj->vel.x -= frictionComponent;
|
||||
}
|
||||
else if (obj->vel.x < 0)
|
||||
{
|
||||
obj->vel.x += obj->bulletClass->Friction.x;
|
||||
obj->vel.x += frictionComponent;
|
||||
}
|
||||
|
||||
if (obj->vel.y > 0)
|
||||
{
|
||||
obj->vel.y -= obj->bulletClass->Friction.y;
|
||||
obj->vel.y -= frictionComponent;
|
||||
}
|
||||
else if (obj->vel.y < 0)
|
||||
{
|
||||
obj->vel.y += obj->bulletClass->Friction.y;
|
||||
obj->vel.y += frictionComponent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -482,7 +486,7 @@ static void LoadBullet(
|
||||
b->SpeedLow = MIN(b->SpeedLow, b->SpeedHigh);
|
||||
b->SpeedHigh = MAX(b->SpeedLow, b->SpeedHigh);
|
||||
LoadBool(&b->SpeedScale, node, "SpeedScale");
|
||||
LoadVec2i(&b->Friction, node, "Friction");
|
||||
LoadInt(&b->Friction, node, "Friction");
|
||||
if (json_find_first_label(node, "Range"))
|
||||
{
|
||||
LoadInt(&b->RangeLow, node, "Range");
|
||||
@@ -605,16 +609,7 @@ void BulletTerminate(BulletClasses *bullets)
|
||||
|
||||
void BulletAdd(const AddBullet add)
|
||||
{
|
||||
Vec2i pos = add.MuzzlePos;
|
||||
if (!Vec2iEqual(add.BulletClass->Size, Vec2iZero()))
|
||||
{
|
||||
const int maxSize = MAX(
|
||||
add.BulletClass->Size.x, add.BulletClass->Size.y);
|
||||
double x, y;
|
||||
GetVectorsForRadians(add.Angle, &x, &y);
|
||||
pos = Vec2iAdd(pos, Vec2iReal2Full(
|
||||
Vec2iNew((int)round(x * maxSize), (int)round(y * maxSize))));
|
||||
}
|
||||
const Vec2i pos = add.MuzzlePos;
|
||||
TMobileObject *obj = CArrayGet(&gMobObjs, MobObjAdd(pos, add.PlayerIndex));
|
||||
obj->vel = GetFullVectorsForRadians(add.Angle);
|
||||
SetBulletProps(
|
||||
|
@@ -66,7 +66,7 @@ typedef struct
|
||||
int SpeedLow;
|
||||
int SpeedHigh;
|
||||
bool SpeedScale; // whether to scale X/Y speed based on perspective
|
||||
Vec2i Friction; // Amount to subtract from velocity per tick
|
||||
int Friction; // Amount to subtract from velocity per tick
|
||||
// -1 is infinite range
|
||||
int RangeLow;
|
||||
int RangeHigh;
|
||||
|
@@ -103,7 +103,8 @@ bool IsCollisionWallOrEdge(Map *map, Vec2i pos, Vec2i size)
|
||||
return IsCollisionWithWall(pos, size);
|
||||
}
|
||||
|
||||
int ItemsCollide(TTileItem *item1, TTileItem *item2, Vec2i pos)
|
||||
static bool ItemsCollide(
|
||||
const TTileItem *item1, const TTileItem *item2, const Vec2i pos)
|
||||
{
|
||||
int dx = abs(pos.x - item2->x);
|
||||
int dy = abs(pos.y - item2->y);
|
||||
@@ -178,6 +179,41 @@ TTileItem *GetItemOnTileInCollision(
|
||||
|
||||
return NULL;
|
||||
}
|
||||
void CollideAllItems(
|
||||
const TTileItem *item, const Vec2i pos,
|
||||
const int mask, const CollisionTeam team, const bool isDogfight,
|
||||
CollideItemFunc func, void *data)
|
||||
{
|
||||
const Vec2i tv = Vec2iToTile(pos);
|
||||
Vec2i dv;
|
||||
// Check collisions with all other items on this tile, in all 8 directions
|
||||
for (dv.y = -1; dv.y <= 1; dv.y++)
|
||||
{
|
||||
for (dv.x = -1; dv.x <= 1; dv.x++)
|
||||
{
|
||||
const Vec2i dtv = Vec2iAdd(tv, dv);
|
||||
if (!MapIsTileIn(&gMap, dtv))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
CArray *tileThings = &MapGetTile(&gMap, dtv)->things;
|
||||
for (int i = 0; i < (int)tileThings->size; i++)
|
||||
{
|
||||
TTileItem *ti = ThingIdGetTileItem(CArrayGet(tileThings, i));
|
||||
// Don't collide if items are on the same team
|
||||
if (!CollisionIsOnSameTeam(ti, team, isDogfight))
|
||||
{
|
||||
if (item != ti &&
|
||||
(ti->flags & mask) &&
|
||||
ItemsCollide(item, ti, pos))
|
||||
{
|
||||
func(ti, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec2i GetWallBounceFullPos(
|
||||
const Vec2i startFull, const Vec2i newFull, Vec2i *velFull)
|
||||
|
@@ -73,6 +73,11 @@ bool CollisionIsOnSameTeam(
|
||||
const TTileItem *i, const CollisionTeam team, const bool isDogfight);
|
||||
TTileItem *GetItemOnTileInCollision(
|
||||
TTileItem *item, Vec2i pos, int mask, CollisionTeam team, int isDogfight);
|
||||
typedef void (*CollideItemFunc)(TTileItem *, void *);
|
||||
void CollideAllItems(
|
||||
const TTileItem *item, const Vec2i pos,
|
||||
const int mask, const CollisionTeam team, const bool isDogfight,
|
||||
CollideItemFunc func, void *data);
|
||||
|
||||
// Resolve wall bounces
|
||||
Vec2i GetWallBounceFullPos(
|
||||
|
@@ -510,12 +510,16 @@ void MobObjDestroy(int id)
|
||||
m->isInUse = false;
|
||||
}
|
||||
|
||||
int HitItem(TMobileObject *obj, Vec2i pos)
|
||||
typedef struct
|
||||
{
|
||||
bool HasHit;
|
||||
bool MultipleHits;
|
||||
bool HasFirstCollision;
|
||||
TMobileObject *Obj;
|
||||
} HitItemData;
|
||||
static void HitItemFunc(TTileItem *ti, void *data);
|
||||
bool HitItem(TMobileObject *obj, const Vec2i pos, const bool multipleHits)
|
||||
{
|
||||
TTileItem *item;
|
||||
int hasHit;
|
||||
Vec2i realPos = Vec2iFull2Real(pos);
|
||||
|
||||
// Don't hit if no damage dealt
|
||||
// This covers non-damaging debris explosions
|
||||
if (obj->bulletClass->Power <= 0 &&
|
||||
@@ -524,18 +528,36 @@ int HitItem(TMobileObject *obj, Vec2i pos)
|
||||
return 0;
|
||||
}
|
||||
|
||||
item = GetItemOnTileInCollision(
|
||||
&obj->tileItem, realPos, TILEITEM_CAN_BE_SHOT, COLLISIONTEAM_NONE,
|
||||
gCampaign.Entry.Mode == CAMPAIGN_MODE_DOGFIGHT);
|
||||
hasHit = DamageSomething(
|
||||
obj->vel, obj->bulletClass->Power, obj->flags, obj->player,
|
||||
item,
|
||||
obj->bulletClass->Special,
|
||||
obj->soundLock <= 0 ? &obj->bulletClass->HitSound : NULL,
|
||||
true);
|
||||
if (hasHit && obj->soundLock <= 0)
|
||||
{
|
||||
obj->soundLock += SOUND_LOCK_MOBILE_OBJECT;
|
||||
}
|
||||
return hasHit;
|
||||
// Get all items that collide
|
||||
HitItemData data;
|
||||
data.HasHit = false;
|
||||
data.MultipleHits = multipleHits;
|
||||
data.HasFirstCollision = false;
|
||||
data.Obj = obj;
|
||||
CollideAllItems(
|
||||
&obj->tileItem, Vec2iFull2Real(pos),
|
||||
TILEITEM_CAN_BE_SHOT, COLLISIONTEAM_NONE,
|
||||
gCampaign.Entry.Mode == CAMPAIGN_MODE_DOGFIGHT,
|
||||
HitItemFunc, &data);
|
||||
return data.HasHit;
|
||||
}
|
||||
static void HitItemFunc(TTileItem *ti, void *data)
|
||||
{
|
||||
HitItemData *hData = data;
|
||||
if (hData->HasFirstCollision && !hData->MultipleHits)
|
||||
{
|
||||
return;
|
||||
}
|
||||
hData->HasFirstCollision = true;
|
||||
hData->HasHit = DamageSomething(
|
||||
hData->Obj->vel, hData->Obj->bulletClass->Power,
|
||||
hData->Obj->flags, hData->Obj->player,
|
||||
ti,
|
||||
hData->Obj->bulletClass->Special,
|
||||
hData->Obj->soundLock <= 0 ? &hData->Obj->bulletClass->HitSound : NULL,
|
||||
true);
|
||||
if (hData->HasHit && hData->Obj->soundLock <= 0)
|
||||
{
|
||||
hData->Obj->soundLock += SOUND_LOCK_MOBILE_OBJECT;
|
||||
}
|
||||
}
|
||||
|
@@ -155,7 +155,7 @@ void MobObjsTerminate(void);
|
||||
int MobObjAdd(Vec2i fullpos, int player);
|
||||
void MobObjDestroy(int id);
|
||||
void MobileObjectUpdate(TMobileObject *obj, int ticks);
|
||||
int HitItem(TMobileObject *obj, Vec2i pos);
|
||||
bool HitItem(TMobileObject *obj, const Vec2i pos, const bool multipleHits);
|
||||
|
||||
bool UpdateMobileObject(TMobileObject *obj, const int ticks);
|
||||
|
||||
|
@@ -248,7 +248,7 @@ void SoundPlayAtPosition(
|
||||
for (;;)
|
||||
{
|
||||
channel = Mix_PlayChannel(-1, data, 0);
|
||||
if (channel >= 0)
|
||||
if (channel >= 0 || device->channels > 128)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@@ -238,8 +238,15 @@ static void LoadGunDescription(
|
||||
|
||||
LoadInt(&g->MuzzleHeight, node, "MuzzleHeight");
|
||||
g->MuzzleHeight *= Z_FACTOR;
|
||||
if (json_find_first_label(node, "Elevation"))
|
||||
{
|
||||
LoadInt(&g->ElevationLow, node, "Elevation");
|
||||
g->ElevationHigh = g->ElevationLow;
|
||||
}
|
||||
LoadInt(&g->ElevationLow, node, "ElevationLow");
|
||||
LoadInt(&g->ElevationHigh, node, "ElevationHigh");
|
||||
g->ElevationLow = MIN(g->ElevationLow, g->ElevationHigh);
|
||||
g->ElevationHigh = MAX(g->ElevationLow, g->ElevationHigh);
|
||||
if (json_find_first_label(node, "MuzzleFlashParticle"))
|
||||
{
|
||||
tmp = GetString(node, "MuzzleFlashParticle");
|
||||
|
Reference in New Issue
Block a user