diff --git a/data/bullets.json b/data/bullets.json index 2507ad172..835816424 100644 --- a/data/bullets.json +++ b/data/bullets.json @@ -1,5 +1,5 @@ { - "Version": 1, + "Version": 2, "DefaultBullet": { "Pic": { "Type": "Directional", @@ -31,7 +31,8 @@ "Name": "mg", "Speed": 768, "Range": 60, - "Power": 10 + "Power": 10, + "Mass": 10.0 }, { "Name": "shotgun", @@ -41,7 +42,8 @@ }, "Speed": 640, "Range": 50, - "Power": 15 + "Power": 15, + "Mass": 15.0 }, { "Name": "flame", @@ -53,6 +55,7 @@ "Speed": 384, "Range": 30, "Power": 12, + "Mass": 1.0, "Size": [10, 10], "Special": "Flame", "Spark": "", @@ -73,6 +76,7 @@ "Speed": 1024, "Range": 90, "Power": 20, + "Mass": 20.0, "Size": [4, 4] }, { @@ -85,6 +89,7 @@ "Speed": 1024, "Range": 90, "Power": 50, + "Mass": 50.0, "Size": [4, 4] }, { @@ -92,6 +97,7 @@ "Speed": 640, "Range": 50, "Power": 40, + "Mass": 40.0, "HurtAlways": true }, { @@ -260,7 +266,8 @@ "Spark": "spark_blue", "Speed": 1280, "Range": 25, - "Power": 6 + "Power": 6, + "Mass": 1.0 }, { "Name": "heatseeker", @@ -271,6 +278,7 @@ "Speed": 512, "Range": 60, "Power": 20, + "Mass": 40.0, "Size": [6, 6], "Spark": "boom", "HitSounds": { @@ -290,6 +298,7 @@ "Speed": 768, "Range": 45, "Power": 15, + "Mass": 15.0, "Erratic": true }, { @@ -350,6 +359,7 @@ "Speed": 700, "Range": 70, "Power": 12, + "Mass": 15.0, "Size": [4, 4], "Spark": "boom", "HitSounds": { @@ -389,6 +399,7 @@ "Speed": 256, "Range": 53, "Power": 5, + "Mass": 5.0, "Size": [14, 10], "HurtAlways": true, "Persists": true, @@ -415,6 +426,7 @@ "Speed": 192, "Range": 71, "Power": 5, + "Mass": 5.0, "Size": [14, 10], "HurtAlways": true, "Persists": true, @@ -441,6 +453,7 @@ "Speed": 128, "Range": 79, "Power": 5, + "Mass": 5.0, "Size": [14, 10], "HurtAlways": true, "Persists": true, @@ -573,6 +586,7 @@ "Speed": 0, "Range": 27, "Power": 3, + "Mass": 10.0, "Size": [64, 64], "Persists": true, "Spark": "", @@ -615,7 +629,8 @@ }, "Speed": 1100, "Range": 27, - "Power": 12 + "Power": 12, + "Mass": 5.0 } ] } diff --git a/missions/doom.cdogscpn/bullets.json b/missions/doom.cdogscpn/bullets.json index 6a6831793..f3118a037 100644 --- a/missions/doom.cdogscpn/bullets.json +++ b/missions/doom.cdogscpn/bullets.json @@ -1,5 +1,5 @@ { - "Version": 1, + "Version": 2, "Bullets": [ { "Name": "10mm", @@ -9,7 +9,8 @@ }, "Speed": 1100, "Range": 50, - "Power": 10 + "Power": 10, + "Mass": 5.0 }, { "Name": "fireball", @@ -21,6 +22,7 @@ "Speed": 350, "Range": 200, "Power": 18, + "Mass": 18.0, "Size": [3, 3], "Special": "Flame", "Spark": "fireball_hit", @@ -40,6 +42,7 @@ "Speed": 550, "Range": 300, "Power": 40, + "Mass": 40.0, "Size": [3, 3], "Special": "Flame", "Spark": "fireball_green_hit", @@ -50,4 +53,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/cdogs/actors.c b/src/cdogs/actors.c index 1d754430d..0fbba248f 100644 --- a/src/cdogs/actors.c +++ b/src/cdogs/actors.c @@ -1441,8 +1441,6 @@ void ActorAddBloodSplatters(TActor *a, const int power, const Vec2i hitVector) int bloodPower = power * 2; // Randomly cycle through the blood types int bloodSize = 1; - // Spray the blood back with the shot if pushback enabled - const bool shotsPushBack = ConfigGetBool(&gConfig, "Game.ShotsPushback"); while (bloodPower > 0) { Emitter *em = NULL; @@ -1463,18 +1461,9 @@ void ActorAddBloodSplatters(TActor *a, const int power, const Vec2i hitVector) { bloodSize = 1; } - Vec2i vel; - if (shotsPushBack) - { - vel = Vec2iScaleDiv( - Vec2iScale(hitVector, (rand() % 8 + 8) * power), - 15 * SHOT_IMPULSE_DIVISOR); - } - else - { - vel = Vec2iScaleDiv( - Vec2iScale(hitVector, rand() % 8 + 8), 20); - } + const Vec2i vel = Vec2iScaleDiv( + Vec2iScale(hitVector, (rand() % 8 + 8) * power), + 15 * SHOT_IMPULSE_DIVISOR); EmitterStart(em, a->Pos, 10, vel); switch (ga) { diff --git a/src/cdogs/bullet_class.c b/src/cdogs/bullet_class.c index 8d09e5cb2..504255ef4 100644 --- a/src/cdogs/bullet_class.c +++ b/src/cdogs/bullet_class.c @@ -407,7 +407,8 @@ static bool HitItemFunc(TTileItem *ti, void *data) int targetUID = -1; hData->HitType = GetHitType(ti, hData->Obj, &targetUID); Damage( - hData->Obj->vel, hData->Obj->bulletClass->Power, + hData->Obj->vel, + hData->Obj->bulletClass->Power, hData->Obj->bulletClass->Mass, hData->Obj->flags, hData->Obj->PlayerUID, hData->Obj->ActorUID, ti->kind, targetUID, hData->Obj->bulletClass->Special); @@ -459,9 +460,10 @@ static HitType GetHitType( -#define VERSION 1 +#define VERSION 2 static void LoadBullet( - BulletClass *b, json_t *node, const BulletClass *defaultBullet); + BulletClass *b, json_t *node, const BulletClass *defaultBullet, + const int version); void BulletInitialize(BulletClasses *bullets) { memset(bullets, 0, sizeof *bullets); @@ -486,21 +488,22 @@ void BulletLoadJSON( if (defaultNode != NULL) { BulletClassFree(&bullets->Default); - LoadBullet(&bullets->Default, defaultNode->child, NULL); + LoadBullet(&bullets->Default, defaultNode->child, NULL, version); } json_t *bulletsNode = json_find_first_label(bulletNode, "Bullets")->child; for (json_t *child = bulletsNode->child; child; child = child->next) { BulletClass b; - LoadBullet(&b, child, &bullets->Default); + LoadBullet(&b, child, &bullets->Default, version); CArrayPushBack(classes, &b); } bullets->root = bulletNode; } static void LoadBullet( - BulletClass *b, json_t *node, const BulletClass *defaultBullet) + BulletClass *b, json_t *node, const BulletClass *defaultBullet, + const int version) { memset(b, 0, sizeof *b); if (defaultBullet != NULL) @@ -565,6 +568,17 @@ static void LoadBullet( b->RangeLow = MIN(b->RangeLow, b->RangeHigh); b->RangeHigh = MAX(b->RangeLow, b->RangeHigh); LoadInt(&b->Power, node, "Power"); + + if (version < 2) + { + // Old version default mass = power + b->Mass = b->Power; + } + else + { + LoadDouble(&b->Mass, node, "Mass"); + } + LoadVec2i(&b->Size, node, "Size"); tmp = NULL; LoadStr(&tmp, node, "Special"); diff --git a/src/cdogs/bullet_class.h b/src/cdogs/bullet_class.h index adb77203d..67b02bb18 100644 --- a/src/cdogs/bullet_class.h +++ b/src/cdogs/bullet_class.h @@ -72,6 +72,7 @@ typedef struct int RangeLow; int RangeHigh; int Power; + double Mass; Vec2i Size; special_damage_e Special; bool HurtAlways; diff --git a/src/cdogs/config.c b/src/cdogs/config.c index 3222a96c7..5e634f14f 100644 --- a/src/cdogs/config.c +++ b/src/cdogs/config.c @@ -557,7 +557,6 @@ Config ConfigDefault(void) "SwitchMoveStyle", SWITCHMOVE_SLIDE, SWITCHMOVE_SLIDE, SWITCHMOVE_NONE, StrSwitchMoveStyle, SwitchMoveStyleStr)); - ConfigGroupAdd(&game, ConfigNewBool("ShotsPushback", true)); ConfigGroupAdd(&game, ConfigNewEnum( "AllyCollision", ALLYCOLLISION_REPEL, ALLYCOLLISION_NORMAL, ALLYCOLLISION_NONE, diff --git a/src/cdogs/game_events.h b/src/cdogs/game_events.h index ea066acba..41a61d18e 100644 --- a/src/cdogs/game_events.h +++ b/src/cdogs/game_events.h @@ -70,8 +70,6 @@ typedef enum GAME_EVENT_ACTOR_STATE, GAME_EVENT_ACTOR_DIR, GAME_EVENT_ACTOR_SLIDE, - // TODO: event only used by actor hit and screen boundaries - // If the latter is removed, it can be incorporated into actor hit GAME_EVENT_ACTOR_IMPULSE, GAME_EVENT_ACTOR_SWITCH_GUN, GAME_EVENT_ACTOR_PICKUP_ALL, diff --git a/src/cdogs/handle_game_events.c b/src/cdogs/handle_game_events.c index 19e5afde5..ae67e2eb9 100644 --- a/src/cdogs/handle_game_events.c +++ b/src/cdogs/handle_game_events.c @@ -338,9 +338,10 @@ static void HandleGameEvent( } if (!gCampaign.IsClient) { + // TODO: melee hitback (vel)? Damage( Vec2iZero(), - b->Power, + b->Power, b->Mass, a->flags, a->PlayerUID, a->uid, (TileItemKind)e.u.Melee.TargetKind, e.u.Melee.TargetUID, SPECIAL_NONE); diff --git a/src/cdogs/net_server.c b/src/cdogs/net_server.c index 8f1d2c353..8d7cf7dd3 100644 --- a/src/cdogs/net_server.c +++ b/src/cdogs/net_server.c @@ -419,7 +419,6 @@ void NetServerSendGameStartMessages(NetServer *n, const int peerId) SendConfig(&gConfig, "Game.Ammo", n, peerId); SendConfig(&gConfig, "Game.Fog", n, peerId); SendConfig(&gConfig, "Game.SightRange", n, peerId); - SendConfig(&gConfig, "Game.ShotsPushback", n, peerId); SendConfig(&gConfig, "Game.AllyCollision", n, peerId); NetServerSendMsg(n, peerId, GAME_EVENT_NET_GAME_START, NULL); diff --git a/src/cdogs/objs.c b/src/cdogs/objs.c index 1ce62b104..23ff427db 100644 --- a/src/cdogs/objs.c +++ b/src/cdogs/objs.c @@ -211,6 +211,7 @@ bool HasHitSound( static void DoDamageCharacter( const Vec2i hitVector, const int power, + const double mass, const int flags, const int playerUID, const int uid, @@ -219,6 +220,7 @@ static void DoDamageCharacter( void Damage( const Vec2i hitVector, const int power, + const double mass, const int flags, const int playerUID, const int uid, @@ -230,7 +232,7 @@ void Damage( case KIND_CHARACTER: DoDamageCharacter( hitVector, - power, flags, playerUID, uid, + power, mass, flags, playerUID, uid, ActorGetByUID(targetUID), special); break; case KIND_OBJECT: @@ -252,6 +254,7 @@ void Damage( static void DoDamageCharacter( const Vec2i hitVector, const int power, + const double mass, const int flags, const int playerUID, const int uid, @@ -262,12 +265,16 @@ static void DoDamageCharacter( CASSERT(actor->isInUse, "Cannot damage nonexistent player"); CASSERT(CanHitCharacter(flags, uid, actor), "damaging undamageable actor"); - if (ConfigGetBool(&gConfig, "Game.ShotsPushback")) + // Shot pushback, based on mass and velocity + const double impulseFactor = mass / SHOT_IMPULSE_DIVISOR; + const Vec2i vel = Vec2iNew( + (int)Round(hitVector.x * impulseFactor), + (int)Round(hitVector.y * impulseFactor)); + if (!Vec2iIsZero(vel)) { GameEvent ei = GameEventNew(GAME_EVENT_ACTOR_IMPULSE); ei.u.ActorImpulse.UID = actor->uid; - ei.u.ActorImpulse.Vel = Vec2i2Net(Vec2iScaleDiv( - Vec2iScale(hitVector, power), SHOT_IMPULSE_DIVISOR)); + ei.u.ActorImpulse.Vel = Vec2i2Net(vel); ei.u.ActorImpulse.Pos = Vec2i2Net(actor->Pos); GameEventsEnqueue(&gGameEvents, ei); } diff --git a/src/cdogs/objs.h b/src/cdogs/objs.h index 64480217c..7cd2e366c 100644 --- a/src/cdogs/objs.h +++ b/src/cdogs/objs.h @@ -105,6 +105,7 @@ bool HasHitSound( void Damage( const Vec2i hitVector, const int power, + const double mass, const int flags, const int playerUID, const int uid, const TileItemKind targetKind, const int targetUID, const special_damage_e special);