diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d3c0ab3b2..9ed6e6f8f 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -5,6 +5,7 @@ D1X-Rebirth Changelog main/menu.c, main/scores.c, main/scores.h: Move all globals in scores.c into struct members/local variables main/game.c, main/newdemo.c: Don't make another Game_wind when advancing a level, fixing failed asserts / slow turning arch/sdl/window.c: Don't send an EVENT_WINDOW_DEACTIVATED when closing a window if it wasn't the front window, now the game works properly after you're shown on the high scores +main/collide.c, main/object.c, main/object.h, main/state.c: Introduced hitobj_list for persistent weapon objects to keep track of multiple objects the weapon is in contect with to prevent it from doing FPS-based damage; Made persistent weapon objects not die on debris but just decrease their shields like when an ordinary player/robot is hit - makes more sense 20100207 -------- diff --git a/main/collide.c b/main/collide.c index fff43687c..eb2664ea2 100644 --- a/main/collide.c +++ b/main/collide.c @@ -899,6 +899,24 @@ void collide_robot_and_weapon( object * robot, object * weapon, vms_vector *coll robot->rtype.pobj_info.tmap_override = Ugly_robot_texture % NumTextures; } +#if 1 + /* + * Check if persistent weapon already hit this object. If yes, abort. + * If no, add this object to hitobj_list and do it's damage. + */ + if (weapon->mtype.phys_info.flags & PF_PERSISTENT) + { + if (!hitobj_list[weapon-Objects][robot-Objects]) + { + hitobj_list[weapon-Objects][robot-Objects] = 1; + weapon->ctype.laser_info.last_hitobj = robot-Objects; + } + else + { + return; + } + } +#else // If a persistent weapon hit robot most recently, quick abort, else we cream the same robot many times, // depending on frame rate. if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { @@ -907,6 +925,7 @@ void collide_robot_and_weapon( object * robot, object * weapon, vms_vector *coll else weapon->ctype.laser_info.last_hitobj = robot-Objects; } +#endif if (weapon->ctype.laser_info.parent_signature == robot->signature) return; @@ -1203,12 +1222,31 @@ void collide_player_and_weapon( object * player, object * weapon, vms_vector *co damage = fixmul(damage, weapon->ctype.laser_info.multiplier); +#if 1 + /* + * Check if persistent weapon already hit this object. If yes, abort. + * If no, add this object to hitobj_list and do it's damage. + */ + if (weapon->mtype.phys_info.flags & PF_PERSISTENT) + { + if (!hitobj_list[weapon-Objects][player-Objects]) + { + hitobj_list[weapon-Objects][player-Objects] = 1; + weapon->ctype.laser_info.last_hitobj = player-Objects; + } + else + { + return; + } + } +#else if (weapon->mtype.phys_info.flags & PF_PERSISTENT) { if (weapon->ctype.laser_info.last_hitobj == player-Objects) return; else weapon->ctype.laser_info.last_hitobj = player-Objects; } +#endif if (player->id == Player_num) { @@ -1446,7 +1484,8 @@ void collide_weapon_and_debris( object * weapon, object * debris, vms_vector *co if ( Weapon_info[weapon->id].damage_radius ) explode_badass_weapon(weapon); maybe_kill_weapon(weapon,debris); - weapon->flags |= OF_SHOULD_BE_DEAD; + if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) + weapon->flags |= OF_SHOULD_BE_DEAD; } return; } diff --git a/main/object.c b/main/object.c index 0b596a340..66abeaf69 100644 --- a/main/object.c +++ b/main/object.c @@ -83,6 +83,7 @@ void obj_detach_one(object *sub); */ ubyte CollisionResult[MAX_OBJECT_TYPES][MAX_OBJECT_TYPES]; +ubyte hitobj_list[MAX_OBJECTS][MAX_OBJECTS]; // last_hitobj of laser_inof struct can only keep track of one object. Still a persistent laser can hit several objects at the same time. This list keeps track of those while last_hitobj will only represent the most recent (the last) hitobj. object *ConsoleObject; //the object that is the player @@ -1129,6 +1130,7 @@ int obj_create(ubyte type,ubyte id,int segnum,vms_vector *pos, obj->mtype.phys_info.flags |= (Weapon_info[obj->id].persistent*PF_PERSISTENT); obj->ctype.laser_info.creation_time = GameTime; obj->ctype.laser_info.last_hitobj = -1; + memset(&hitobj_list[objnum], 0, sizeof(ubyte)*MAX_OBJECTS); obj->ctype.laser_info.multiplier = F1_0; } diff --git a/main/object.h b/main/object.h index f922f2b48..6e0090f0a 100644 --- a/main/object.h +++ b/main/object.h @@ -171,11 +171,13 @@ typedef struct laser_info { short parent_num; // The object's parent's number int parent_signature; // The object's parent's signature... fix creation_time; // Absolute time of creation. - short last_hitobj; // For persistent weapons (survive object collision), object it most recently hit. + short last_hitobj; // For persistent weapons (survive object collision), object it most recently hit. NOTE: SEE hitobj_list!!! short track_goal; // Object this object is tracking. fix multiplier; // Power if this is a fusion bolt (or other super weapon to be added). } __pack__ laser_info; +extern ubyte hitobj_list[MAX_OBJECTS][MAX_OBJECTS]; + typedef struct explosion_info { fix spawn_time; // when lifeleft is < this, spawn another fix delete_time; // when to delete object diff --git a/main/state.c b/main/state.c index bbeb98d37..ff3502a92 100644 --- a/main/state.c +++ b/main/state.c @@ -779,6 +779,17 @@ RetryObjectLoading: } obj_link(i,segnum); } + + // If weapon, restore the most recent hitobj to the list + if (obj->type == OBJ_WEAPON) + { + if (obj->ctype.laser_info.last_hitobj > 0 && obj->ctype.laser_info.last_hitobj < MAX_OBJECTS) + { + memset(&hitobj_list[i], 0, sizeof(ubyte)*MAX_OBJECTS); + hitobj_list[i][obj->ctype.laser_info.last_hitobj] = 1; + printf("RESTORE WEAPON[%i] LHO[%i]\n",i,obj->ctype.laser_info.last_hitobj); + } + } } special_reset_objects();