[Xpilot-hacks] Red alert! Red alert!
Bob Glickstein
bobg at emphatic.com
Thu Aug 2 21:09:33 ADT 2001
Captain! We've taken a hit! Maneuvering thrusters and shields at
reduced capacity. Incoming fire, bearing 110!
Raise shields! Set course 290, full power -- engage!
Helm is sluggish, sir! Passing through 320... 310... Incoming fire
penetrating our shields, sir! Fuel tank 2 is venting into space.
Maintenance 'bots are responding!
Take evasive action, full power to the engines.
Captain, the superstructure is weakened! It can't take the strain
of this acceleration!
Maintain full power!
Structural stress increasing, but the enemy is falling
behind... Captain! Obstacle ahead!
Emergency stop!
The controls aren't responding! I can't disengage the main engi--
BLAM!
Ah, now *that's* a space battle. And here's the patch you need
(against version 4.4.1) to experience it firsthand: my "damage" hack.
It's always bothered me that the merest touch from a shot in the
XPilot universe is enough to blast my hardy craft to smithereens, so
I've made it more realistic -- and outdone myself this time, if I say
so myself. It's still rough around the edges -- some duplicated code
needs to be refactored, some code that's scattered around needs to be
gathered together, some floating-point values can be converted to
integers, several constants can still stand some tweaking, and so on
-- but I've been enjoying the hell out of it for the past couple of
weeks and decided to share sooner rather than later, especially since
I won't get time to clean this up for at least several more weeks.
Some notes on the patch:
- It modifies the client-server protocol (but I again didn't update
the protocol version info, not being sure how). The server now
communicates damage-report info to the client.
- It adds four new files: client/items/itemMainbot.xbm,
common/systems.h, common/systems.c, and server/damage.h. These
files are attached to this message after the patch.
- Individual ship subsystems (and damage to them) are now modeled,
but there are still many systems, particularly optional ones, yet
to model.
- Damage is presently only modeled for collision with shots and
cluster debris -- not for laser hits, other collisions, etc. The
amount of damage corresponds to the kinetic energy of the shot
collision.
- There's a new pick-up item: the maintbot. By default, ships start
with one maintbot each. When systems are damaged, the ship's
maintbots leap into action, repairing them (at the cost of a few
units of fuel) continuously until they're back at 100%. Sometimes
the maintbots must repair themselves!
- The diff hunk at server/collision.c:763 -- moving the Delta_mv call
to after the Player_collides_with_killing_shot() call -- is
required so that the kinetic energy of the impact can be calculated
(based on the relative velocity) in Player_collides_with_killing_shot().
- Here's what can presently be damaged, and the effect that the
damage can have:
- The ship's superstructure. If damaged, then accelerating can
worsen the damage. If the damage exceeds a certain threshold,
the ship is vulnerable to spontaneously pulling itself apart.
- The ship's controls. These have multiple redundancy built in,
but if very damaged, your keypresses (and keyreleases) can fail
to reach the intended systems.
- Fuel tanks. If one of these is hit while very full, it's likely
to blow you up; but if it doesn't, it'll begin to leak (and
you'll see it leaking).
- Main thruster. The more damaged it is, the less power it can
produce, and with variable reliability.
- Turn thrusters. Ditto.
- Shields. When damaged, they may not absorb all the energy of an
incoming shot, allowing some to penetrate to the ship and cause
further damage.
- Guns. The more damaged they are, the less energy and accuracy
they can impart to the shots they fire.
- Maintenance. When damaged, repairs take longer.
Here's the patch, followed by the four new files. Enjoy!
-------------- next part --------------
Index: src/Makefile.std
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/Makefile.std,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 Makefile.std
--- src/Makefile.std 2001/07/01 18:31:25 1.1.1.3
+++ src/Makefile.std 2001/08/02 23:34:01
@@ -223,14 +223,14 @@
list.o math.o net.o \
portability.o randommt.o \
shipshape.o socklib.o \
- strcasecmp.o strdup.o strlcpy.o \
+ strcasecmp.o strdup.o strlcpy.o systems.o \
xpmemory.o
SRCS0 = checknames.c config.c error.c \
list.c math.c net.c \
portability.c randommt.c \
shipshape.c socklib.c \
- strcasecmp.c strdup.c strlcpy.c \
+ strcasecmp.c strdup.c strlcpy.c systems.c \
xpmemory.c
#
@@ -556,6 +556,7 @@
strcasecmp.o: strcasecmp.c
strdup.o: strdup.c error.h commonproto.h types.h
strlcpy.o: strlcpy.c commonproto.h types.h
+systems.o: systems.c systems.h
xpmemory.o: xpmemory.c error.h commonproto.h types.h
about.o: about.c ../common/version.h ../common/config.h \
../common/const.h ../common/types.h ../common/keys.h paint.h client.h \
Index: src/client/client.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/client.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 client.c
--- src/client/client.c 2001/07/06 23:21:57 1.1.1.4
+++ src/client/client.c 2001/08/02 23:35:07
@@ -80,6 +80,8 @@
int numItemsTime[NUM_ITEMS];/* Number of frames to show this item count */
DFLOAT showItemsTime; /* How long to show changed item count for */
+DFLOAT sys_damage[NUM_SYSTEMS];
+
short autopilotLight;
short lock_id; /* Id of player locked onto */
Index: src/client/client.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/client.h,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 client.h
--- src/client/client.h 2001/07/06 23:21:58 1.1.1.4
+++ src/client/client.h 2001/08/02 23:35:26
@@ -45,6 +45,8 @@
#include "item.h"
#endif
+#include "systems.h"
+
#define SHOW_HUD_INSTRUMENTS (1L << 0)
#define SHOW_HUD_VERTICAL (1L << 1)
#define SHOW_HUD_HORIZONTAL (1L << 2)
@@ -211,6 +213,7 @@
extern DFLOAT showItemsTime;
extern short autopilotLight;
+extern DFLOAT sys_damage[NUM_SYSTEMS];
extern short lock_id; /* Id of player locked onto */
extern short lock_dir; /* Direction of lock */
Index: src/client/netclient.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/netclient.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 netclient.c
--- src/client/netclient.c 2001/07/06 23:21:58 1.1.1.4
+++ src/client/netclient.c 2001/08/02 23:34:01
@@ -176,6 +176,8 @@
receive_tbl[PKT_LOSEITEM] = Receive_loseitem;
receive_tbl[PKT_WRECKAGE] = Receive_wreckage;
receive_tbl[PKT_ASTEROID] = Receive_asteroid;
+ receive_tbl[PKT_DAMAGE] = Receive_self_damage;
+
for (i = 0; i < DEBRIS_TYPES; i++) {
receive_tbl[PKT_DEBRIS + i] = Receive_debris;
}
@@ -1486,6 +1488,36 @@
}
Handle_self_items(num_items);
return (rbuf.ptr - rbuf_ptr_start);
+}
+
+int
+Receive_self_damage(void)
+{
+ u_byte ch;
+ unsigned sys_mask;
+ int i, n;
+ DFLOAT damage[NUM_SYSTEMS];
+ char *rbuf_ptr_start = rbuf.ptr;
+
+ n = Packet_scanf(&rbuf, "%c%u", &ch, &sys_mask);
+ if (n <= 0)
+ return n;
+
+ for (i = 0; i < NUM_SYSTEMS; ++i) {
+ damage[i] = 0.0;
+ if (sys_mask & (1 << i)) {
+ if ((rbuf.ptr + sizeof (unsigned long) - rbuf.buf) <= rbuf.len) {
+ unsigned long val;
+ memcpy(&val, rbuf.ptr, sizeof (unsigned long));
+ rbuf.ptr += sizeof (unsigned long);
+ val = ntohl(val);
+ damage[i] = (((DFLOAT) val) / 10.0);
+ }
+ }
+ }
+
+ Handle_self_damage(damage);
+ return (rbuf.ptr - rbuf_ptr_start);
}
/*
Index: src/client/netclient.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/netclient.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 netclient.h
--- src/client/netclient.h 2001/07/01 18:31:26 1.1.1.2
+++ src/client/netclient.h 2001/08/02 23:34:01
@@ -71,6 +71,7 @@
int Receive_debris(void);
int Receive_wreckage(void);
int Receive_asteroid(void);
+int Receive_self_damage(void);
int Receive_fastshot(void);
int Receive_ecm(void);
int Receive_trans(void);
Index: src/client/paint.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/paint.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 paint.h
--- src/client/paint.h 2001/07/01 18:31:26 1.1.1.2
+++ src/client/paint.h 2001/08/02 23:34:01
@@ -199,6 +199,7 @@
u_byte *newNumItems,
int currentTank, int fuel_sum, int fuel_max, int packet_size);
int Handle_self_items(u_byte *newNumItems);
+int Handle_self_damage(DFLOAT *newDamage);
int Handle_modifiers(char *m);
int Handle_damaged(int damaged);
int Handle_destruct(int count);
Index: src/client/paintdata.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/paintdata.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 paintdata.c
--- src/client/paintdata.c 2001/07/01 18:31:26 1.1.1.3
+++ src/client/paintdata.c 2001/08/02 23:34:29
@@ -464,6 +464,12 @@
return 0;
}
+int
+Handle_self_damage(DFLOAT *newDamage)
+{
+ memcpy(sys_damage, newDamage, NUM_SYSTEMS * sizeof(DFLOAT));
+}
+
int Handle_self(int x, int y, int vx, int vy, int newHeading,
float newPower, float newTurnspeed, float newTurnresistance,
int newLockId, int newLockDist, int newLockBearing,
Index: src/client/painthud.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/painthud.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 painthud.c
--- src/client/painthud.c 2001/07/01 18:31:26 1.1.1.3
+++ src/client/painthud.c 2001/08/02 23:34:29
@@ -374,6 +374,8 @@
}
+#define DAMAGE_REPORT_TIME (FPS / 2)
+
void Paint_HUD(void)
{
const int BORDER = 3;
@@ -386,6 +388,9 @@
rect_x, rect_y, rect_width, rect_height;
static int vertSpacing = -1;
static char autopilot[] = "Autopilot";
+ static int last_system = -1;
+ static DFLOAT last_damage;
+ static int damage_report_time = 0;
int modlen = 0;
@@ -646,6 +651,64 @@
- gameFont->descent * 2 - gameFont->ascent * 2,
text_width + 2,
gameFont->ascent + gameFont->descent);
+ }
+
+ /* Damage report */
+ {
+ static int last_width = 0;
+ int next_system = last_system;
+
+ if ((last_system < 0) || (++damage_report_time >= DAMAGE_REPORT_TIME)) {
+ for (i = last_system + 1; i < NUM_SYSTEMS; ++i) {
+ if (sys_damage[i] > 0.0) {
+ next_system = i;
+ break;
+ }
+ }
+
+ if (next_system == last_system) {
+ for (i = 0; i < last_system; ++i) {
+ if (sys_damage[i] > 0.0) {
+ next_system = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (last_system >= 0)
+ Erase_rectangle(WINSCALE(hud_pos_x) - last_width/2,
+ WINSCALE(hud_pos_y + HUD_SIZE - HUD_OFFSET + BORDER) + 2 * gameFont->ascent + gameFont->descent,
+ last_width,
+ gameFont->ascent + gameFont->descent);
+
+ if (next_system >= 0) {
+ DFLOAT damage = sys_damage[next_system];
+ char report[100];
+ int width;
+
+ if (damage > 0.0) {
+ sprintf(report, "%s: %.1f", sys_names[next_system], damage);
+ width = XTextWidth(gameFont, report, strlen(report));
+
+ rd.drawString(dpy, p_draw, gc,
+ WINSCALE(hud_pos_x) - width/2,
+ WINSCALE(hud_pos_y + HUD_SIZE - HUD_OFFSET + BORDER) + 2 * gameFont->ascent + gameFont->descent,
+ report, strlen(report));
+
+ last_width = width;
+
+ if (next_system != last_system)
+ damage_report_time = 0;
+
+ last_system = next_system;
+ } else {
+ damage_report_time = 0;
+ last_system = -1;
+ }
+
+ } else
+ last_system = -1;
}
if (fuelCount > 0) {
Index: src/client/xinit.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/client/xinit.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 xinit.c
--- src/client/xinit.c 2001/07/01 18:31:26 1.1.1.3
+++ src/client/xinit.c 2001/08/02 23:34:29
@@ -86,6 +86,7 @@
#include "items/itemTractorBeam.xbm"
#include "items/itemAutopilot.xbm"
#include "items/itemEmergencyShield.xbm"
+#include "items/itemMaintbot.xbm"
char xinit_version[] = VERSION;
@@ -241,6 +242,11 @@
itemArmor_bits,
"Armor; "
"absorbs shots in the absence of shields"
+ },
+ {
+ itemMaintbot_bits,
+ "Maintbot; "
+ "repairs ship damage"
},
};
#ifdef _WINDOWS
Index: src/common/Imakefile
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/common/Imakefile,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 Imakefile
--- src/common/Imakefile 2001/07/01 18:31:26 1.1.1.2
+++ src/common/Imakefile 2001/08/02 23:34:29
@@ -32,7 +32,7 @@
list.c math.c net.c \
portability.c randommt.c \
shipshape.c socklib.c \
- strcasecmp.c strdup.c strlcpy.c \
+ strcasecmp.c strdup.c strlcpy.c systems.c \
xpmemory.c
# keep this variable consistent with its counterpart in ../Makefile.std
@@ -40,7 +40,7 @@
list.o math.o net.o \
portability.o randommt.o \
shipshape.o socklib.o \
- strcasecmp.o strdup.o strlcpy.o \
+ strcasecmp.o strdup.o strlcpy.o systems.o \
xpmemory.o
NormalLibraryTarget(xpcommon,$(OBJS))
Index: src/common/audio.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/common/audio.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 audio.h
--- src/common/audio.h 2001/07/01 18:31:25 1.1.1.3
+++ src/common/audio.h 2001/08/02 23:34:29
@@ -113,6 +113,7 @@
CANNON_EXPLOSION_SOUND,
ASTEROID_HIT_SOUND,
ASTEROID_BREAK_SOUND,
+ MAINTBOT_PICKUP_SOUND,
MAX_SOUNDS
};
@@ -203,6 +204,7 @@
"cannon_explosion",
"asteroid_hit",
"asteroid_break",
+ "maintbot_pickup",
};
#endif /* _CAUDIO_C_ */
Index: src/common/item.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/common/item.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 item.h
--- src/common/item.h 2001/07/01 18:31:26 1.1.1.3
+++ src/common/item.h 2001/08/02 23:34:29
@@ -47,7 +47,8 @@
ITEM_PHASING = 18,
ITEM_MIRROR = 19,
ITEM_ARMOR = 20,
- NUM_ITEMS = 21
+ ITEM_MAINTBOT = 21,
+ NUM_ITEMS = 22
};
#define ITEM_BIT_FUEL (1U << ITEM_FUEL)
@@ -71,6 +72,7 @@
#define ITEM_BIT_PHASING (1U << ITEM_PHASING)
#define ITEM_BIT_MIRROR (1U << ITEM_MIRROR)
#define ITEM_BIT_ARMOR (1U << ITEM_ARMOR)
+#define ITEM_BIT_MAINTBOT (1U << ITEM_MAINTBOT)
/* Each item is ITEM_SIZE x ITEM_SIZE */
#define ITEM_SIZE 16
Index: src/common/packet.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/common/packet.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 packet.h
--- src/common/packet.h 2001/07/01 18:31:26 1.1.1.2
+++ src/common/packet.h 2001/08/02 23:34:29
@@ -130,7 +130,7 @@
/* packet types: 80 - 89 */
#define PKT_ASTEROID 80
-#define PKT_NOT_USED_81 81
+#define PKT_DAMAGE 81
#define PKT_NOT_USED_82 82
#define PKT_NOT_USED_83 83
#define PKT_NOT_USED_84 84
Index: src/replay/xp-replay.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/replay/xp-replay.c,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 xp-replay.c
--- src/replay/xp-replay.c 2001/07/01 18:31:27 1.1.1.2
+++ src/replay/xp-replay.c 2001/08/02 23:34:29
@@ -97,6 +97,7 @@
#include "items/itemTractorBeam.xbm"
#include "items/itemAutopilot.xbm"
#include "items/itemEmergencyShield.xbm"
+#include "items/itemMaintbot.xbm"
#include "tools/eject.xbm"
#include "tools/fastf.xbm"
@@ -1397,7 +1398,8 @@
itemHyperJump_bits,
itemPhasingDevice_bits,
itemMirror_bits,
- itemArmor_bits
+ itemArmor_bits,
+ itemMaintbot_bits
};
static XFontStruct *loadQueryFont(const char *fontName, GC gc)
Index: src/server/cmdline.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/cmdline.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 cmdline.c
--- src/server/cmdline.c 2001/07/06 23:21:59 1.1.1.4
+++ src/server/cmdline.c 2001/08/02 23:34:29
@@ -2356,6 +2356,16 @@
OPT_ORIGIN_ANY | OPT_VISIBLE
},
{
+ "itemMaintbotProb",
+ "itemMaintbotProb",
+ "1e-9",
+ &World.items[ITEM_MAINTBOT].prob,
+ valReal,
+ Tune_item_probs,
+ "Probability for a Maintbot item to appear.\n",
+ OPT_ORIGIN_ANY | OPT_VISIBLE
+ },
+ {
"initialFuel",
"initialFuel",
"1000",
@@ -2563,6 +2573,26 @@
valInt,
Set_initial_resources,
"How many emergency shields players start with.\n",
+ OPT_ORIGIN_ANY | OPT_VISIBLE
+ },
+ {
+ "initialMaintbots",
+ "initialMaintbots",
+ "1",
+ &World.items[ITEM_MAINTBOT].initial,
+ valInt,
+ Set_initial_resources,
+ "How many maintbots players start with.\n",
+ OPT_ORIGIN_ANY | OPT_VISIBLE
+ },
+ {
+ "maxMaintbots",
+ "maxMaintbots",
+ "8",
+ &World.items[ITEM_MAINTBOT].limit,
+ valInt,
+ Set_initial_resources,
+ "Upper limit on maintbots per player.\n",
OPT_ORIGIN_ANY | OPT_VISIBLE
},
{
Index: src/server/collision.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/collision.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 collision.c
--- src/server/collision.c 2001/07/01 18:31:28 1.1.1.3
+++ src/server/collision.c 2001/08/02 23:39:59
@@ -52,6 +52,7 @@
#include "portability.h"
#include "objpos.h"
#include "asteroid.h"
+#include "damage.h"
char collision_version[] = VERSION;
@@ -235,6 +236,7 @@
static void Player_collides_with_debris(int ind, object *obj);
static void Player_collides_with_asteroid(int ind, wireobject *obj);
static void Player_collides_with_killing_shot(int ind, object *obj);
+static void Player_killed_by_killing_shot(int ind, object *obj);
void Check_collision(void)
@@ -621,6 +623,7 @@
pl->item[ITEM_TRANSPORTER] + pl->item[ITEM_TRACTOR_BEAM] +
pl->item[ITEM_EMERGENCY_SHIELD] + pl->fuel.num_tanks +
pl->item[ITEM_DEFLECTOR] + pl->item[ITEM_HYPERJUMP] +
+ pl->item[ITEM_MAINTBOT] +
pl->item[ITEM_PHASING] + pl->item[ITEM_MIRROR];
if (pl->emergency_shield_left)
count++;
@@ -763,17 +766,17 @@
break;
}
- obj->life = 0;
- if (hit) {
- Delta_mv((object *)pl, (object *)obj);
- }
-
if (BIT(obj->type, KILLING_SHOTS)) {
Player_collides_with_killing_shot(ind, obj);
if (BIT(pl->status, KILLED)) {
return;
}
}
+
+ obj->life = 0;
+ if (hit) {
+ Delta_mv((object *)pl, (object *)obj);
+ }
}
}
@@ -1019,6 +1022,15 @@
}
sound_play_sensors(pl->pos.x, pl->pos.y, TANK_PICKUP_SOUND);
break;
+
+ case ITEM_MAINTBOT:
+ pl->item[item_index]++;
+ LIMIT(pl->item[item_index], 0, World.items[item_index].limit);
+ if (pl->item[item_index] > 0)
+ SET_BIT(pl->have2, HAS2_MAINTBOT);
+ sound_play_sensors(pl->pos.x, pl->pos.y, MAINTBOT_PICKUP_SOUND);
+ break;
+
case NUM_ITEMS:
/* impossible */
break;
@@ -1195,14 +1207,69 @@
}
+static int
+random_compare(const void *a, const void *b)
+{
+ return ((randomMT() % 2) ? 1 : -1);
+}
+
+static int
+check_for_fatal_damage(int ind, object *obj, int system)
+{
+ player *pl = Players[ind];
+
+ switch (system) {
+ case sys_tanks: {
+ DFLOAT factor = (((DFLOAT) pl->fuel.sum) / ((DFLOAT) pl->fuel.max));
+ factor *= rfrac();
+ factor *= (1.0 + pl->damage[sys_tanks]);
+
+ if (factor > DMG_TANK_EXPLOSION_THRESHOLD) {
+ Player_killed_by_killing_shot(ind, obj);
+ return 1;
+ }
+ }
+
+ case sys_structure: {
+ DFLOAT factor = rfrac() * pl->damage[sys_structure];
+ if (factor > DMG_HULL_FAILURE_THRESHOLD) {
+ Player_killed_by_killing_shot(ind, obj);
+ return 1;
+ }
+ }
+ }
+
+ return 0; /* nothing else fatal right now */
+}
+
+static int
+player_has_system(player *pl, int i)
+{
+ return 1; /* xxx player has everything */
+}
+
static void Player_collides_with_killing_shot(int ind, object *obj)
{
player *pl = Players[ind];
int sc;
- DFLOAT drainfactor;
long drain;
int killer;
+ DFLOAT dx = pl->vel.x - obj->vel.x;
+ DFLOAT dy = pl->vel.y - obj->vel.y;
+ DFLOAT rel_velocity = LENGTH(dx, dy);
+ DFLOAT k = rel_velocity * rel_velocity * obj->mass;
+ DFLOAT k_factor, d_factor;
+
+ static DFLOAT k_base = 0.0;
+
+ if (k_base == 0.0) {
+ k_base = ShotsSpeed * ShotsSpeed * ShotsMass;
+ }
+
+ k_factor = k / k_base;
+ d_factor = k_factor;
+
/*
* Player got hit by a potentially deadly object.
*
@@ -1219,6 +1286,8 @@
|| (obj->type == OBJ_TORPEDO
&& BIT(obj->mods.nuclear, NUCLEAR)
&& (int)(rfrac() >= 0.25f))) {
+ d_factor = 0.0;
+
switch (obj->type) {
case OBJ_TORPEDO:
sound_play_sensors(pl->pos.x, pl->pos.y,
@@ -1261,19 +1330,17 @@
PLAYER_EAT_SHOT_SOUND);
if (BIT(pl->used, (HAS_SHIELD|HAS_EMERGENCY_SHIELD))
!= (HAS_SHIELD|HAS_EMERGENCY_SHIELD)) {
-#ifdef DRAINFACTOR
-/* BG: this is bad: one shot causes way too much damage at higher speeds. */
- DFLOAT rel_velocity = LENGTH(pl->vel.x - obj->vel.x,
- pl->vel.y - obj->vel.y);
- drainfactor = (rel_velocity * rel_velocity * ABS(obj->mass))
- / (ShotsSpeed * ShotsSpeed * ShotsMass);
-#else
- drainfactor = 1;
-#endif
- drain = (long)(ED_SHOT_HIT * drainfactor * SHOT_MULT(obj));
+ drain = (long)(ED_SHOT_HIT * k_factor * SHOT_MULT(obj));
Add_fuel(&(pl->fuel), drain);
}
pl->forceVisible = (int)(pl->forceVisible + SHOT_MULT(obj));
+ if (pl->damage[sys_shields]) {
+ DFLOAT r = rfrac();
+
+ d_factor = (k_factor *
+ (1.0 - (1.0 /
+ (1.0 + r * r * pl->damage[sys_shields]))));
+ }
break;
default:
@@ -1286,87 +1353,145 @@
if (!BIT(pl->used, HAS_SHIELD) && BIT(pl->have, HAS_ARMOR)) {
Player_hit_armor(ind);
}
- } else {
- switch (obj->type) {
- case OBJ_TORPEDO:
- case OBJ_SMART_SHOT:
- case OBJ_HEAT_SHOT:
- case OBJ_SHOT:
- if (BIT(obj->status, FROMCANNON)) {
- sound_play_sensors(pl->pos.x, pl->pos.y,
- PLAYER_HIT_CANNONFIRE_SOUND);
- sprintf(msg, "%s was hit by cannonfire.", pl->name);
- Set_message(msg);
- sc = Rate(CANNON_SCORE, pl->score)/4;
- SCORE(ind, -sc,
- OBJ_X_IN_BLOCKS(pl),
- OBJ_Y_IN_BLOCKS(pl),
- "Cannon");
- SET_BIT(pl->status, KILLED);
- return;
- }
+ }
- if (obj->id == NO_ID) {
- sprintf(msg, "%s was killed by %s.", pl->name,
- Describe_shot(obj->type, obj->status,
- obj->mods, 1));
- SCORE(ind, PTS_PR_PL_SHOT,
- OBJ_X_IN_BLOCKS(pl),
- OBJ_Y_IN_BLOCKS(pl),
- "N/A");
- killer = ind;
- } else {
- sprintf(msg, "%s was killed by %s from %s.", pl->name,
- Describe_shot(obj->type, obj->status,
- obj->mods, 1),
- Players[killer=GetInd[obj->id]]->name);
- if (killer == ind) {
- sound_play_sensors(pl->pos.x, pl->pos.y,
- PLAYER_SHOT_THEMSELF_SOUND);
- strcat(msg, " How strange!");
- SCORE(ind, PTS_PR_PL_SHOT,
- OBJ_X_IN_BLOCKS(pl),
- OBJ_Y_IN_BLOCKS(pl),
- Players[killer]->name);
- } else {
- DFLOAT factor;
- Players[killer]->kills++;
- switch (obj->type) {
- case OBJ_SHOT:
- if (BIT(obj->mods.warhead, CLUSTER)) {
- factor = clusterKillScoreMult;
- } else {
- factor = shotKillScoreMult;
- }
- break;
- case OBJ_TORPEDO:
- factor = torpedoKillScoreMult;
- break;
- case OBJ_SMART_SHOT:
- factor = smartKillScoreMult;
- break;
- case OBJ_HEAT_SHOT:
- factor = heatKillScoreMult;
- break;
- default:
- factor = shotKillScoreMult;
- break;
- }
- sc = (int)floor(Rate(Players[killer]->score, pl->score)
- * factor);
- Score_players(killer, sc, pl->name,
- ind, -sc, Players[killer]->name);
- }
- }
- Set_message(msg);
- SET_BIT(pl->status, KILLED);
- Robot_war(ind, killer);
- return;
+ if (d_factor > 0.0) {
+ /* Distribute the energy of the impact among the ship's systems */
+ int sysorder[NUM_SYSTEMS];
+ int num_systems = 0;
+ int system;
+ int i;
+
+ if (IS_HUMAN_PTR(pl))
+ fprintf(stderr, "\n");
+
+ for (i = 0; i < NUM_SYSTEMS; ++i) {
+ if (player_has_system(pl, i))
+ sysorder[num_systems++] = i;
+ }
+
+ /* Now randomize the order in which we'll damage the systems */
+ qsort(sysorder, num_systems, sizeof (int), random_compare);
+
+ for (i = 0; i < num_systems - 1; ++i) {
+ DFLOAT damage = rfrac() * d_factor;
+ system = sysorder[i];
+ pl->damage[system] += d_factor;
+ d_factor -= damage;
+
+ if (check_for_fatal_damage(ind, obj, system))
+ return;
+ }
+
+ system = sysorder[num_systems - 1];
+
+ pl->damage[system] += d_factor;
+ if (check_for_fatal_damage(ind, obj, sysorder[system]))
+ return;
+
+ Make_debris(pl->pos.x, pl->pos.y,
+ pl->vel.x, pl->vel.y,
+ pl->id,
+ pl->team,
+ OBJ_SPARK,
+ 0.1,
+ GRAVITY | OWNERIMMUNE,
+ RED,
+ 4,
+ 16, 16 * (1 + k_factor),
+ 0, RES - 1,
+ 18.0, 18.0 * (1 + k_factor),
+ 3, 16);
+ }
+}
- default:
- break;
- }
+
+static void
+Player_killed_by_killing_shot(int ind, object *obj)
+{
+ player *pl = Players[ind];
+ int sc;
+ int killer;
+
+ switch (obj->type) {
+ case OBJ_TORPEDO:
+ case OBJ_SMART_SHOT:
+ case OBJ_HEAT_SHOT:
+ case OBJ_SHOT:
+ if (BIT(obj->status, FROMCANNON)) {
+ sound_play_sensors(pl->pos.x, pl->pos.y,
+ PLAYER_HIT_CANNONFIRE_SOUND);
+ sprintf(msg, "%s was hit by cannonfire.", pl->name);
+ Set_message(msg);
+ sc = Rate(CANNON_SCORE, pl->score)/4;
+ SCORE(ind, -sc,
+ OBJ_X_IN_BLOCKS(pl),
+ OBJ_Y_IN_BLOCKS(pl),
+ "Cannon");
+ SET_BIT(pl->status, KILLED);
+ return;
+ }
+
+ if (obj->id == NO_ID) {
+ sprintf(msg, "%s was killed by %s.", pl->name,
+ Describe_shot(obj->type, obj->status,
+ obj->mods, 1));
+ SCORE(ind, PTS_PR_PL_SHOT,
+ OBJ_X_IN_BLOCKS(pl),
+ OBJ_Y_IN_BLOCKS(pl),
+ "N/A");
+ killer = ind;
+ } else {
+ sprintf(msg, "%s was killed by %s from %s.", pl->name,
+ Describe_shot(obj->type, obj->status,
+ obj->mods, 1),
+ Players[killer=GetInd[obj->id]]->name);
+ if (killer == ind) {
+ sound_play_sensors(pl->pos.x, pl->pos.y,
+ PLAYER_SHOT_THEMSELF_SOUND);
+ strcat(msg, " How strange!");
+ SCORE(ind, PTS_PR_PL_SHOT,
+ OBJ_X_IN_BLOCKS(pl),
+ OBJ_Y_IN_BLOCKS(pl),
+ Players[killer]->name);
+ } else {
+ DFLOAT factor;
+ Players[killer]->kills++;
+ switch (obj->type) {
+ case OBJ_SHOT:
+ if (BIT(obj->mods.warhead, CLUSTER)) {
+ factor = clusterKillScoreMult;
+ } else {
+ factor = shotKillScoreMult;
+ }
+ break;
+ case OBJ_TORPEDO:
+ factor = torpedoKillScoreMult;
+ break;
+ case OBJ_SMART_SHOT:
+ factor = smartKillScoreMult;
+ break;
+ case OBJ_HEAT_SHOT:
+ factor = heatKillScoreMult;
+ break;
+ default:
+ factor = shotKillScoreMult;
+ break;
+ }
+ sc = (int)floor(Rate(Players[killer]->score, pl->score)
+ * factor);
+ Score_players(killer, sc, pl->name,
+ ind, -sc, Players[killer]->name);
+ }
}
+ Set_message(msg);
+ SET_BIT(pl->status, KILLED);
+ Robot_war(ind, killer);
+ return;
+
+ default:
+ break;
+ }
}
Index: src/server/event.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/event.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 event.c
--- src/server/event.c 2001/07/01 18:31:28 1.1.1.3
+++ src/server/event.c 2001/08/02 23:37:35
@@ -311,6 +311,13 @@
if (key != KEY_SHIELD) /* would interfere with auto-idle-pause.. */
pl->frame_last_busy = frame_loops; /* due to client auto-shield */
+ if (pl->damage[sys_controls] > 0.0) {
+ DFLOAT r = rfrac();
+
+ if (r * r * r * r * pl->damage[sys_controls] > 1.0)
+ continue;
+ }
+
/*
* Allow these functions before a round has started.
*/
Index: src/server/global.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/global.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 global.h
--- src/server/global.h 2001/07/01 18:31:28 1.1.1.3
+++ src/server/global.h 2001/08/02 23:34:29
@@ -80,6 +80,7 @@
extern bool ShotsGravity;
extern int fireRepeatRate;
extern long DEF_BITS, KILL_BITS, DEF_HAVE, DEF_USED, USED_KILL;
+extern long DEF_HAVE2;
extern int GetInd[];
extern int ShutdownServer, ShutdownDelay;
extern bool RawMode;
Index: src/server/item.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/item.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 item.c
--- src/server/item.c 2001/07/01 18:31:28 1.1.1.1
+++ src/server/item.c 2001/08/02 23:34:29
@@ -97,6 +97,8 @@
}
if (pl->item[ITEM_ARMOR] <= 0)
CLR_BIT(pl->have, HAS_ARMOR);
+ if (pl->item[ITEM_MAINTBOT] <= 0)
+ CLR_BIT(pl->have2, HAS2_MAINTBOT);
}
/*
@@ -761,6 +763,11 @@
}
}
break;
+ case ITEM_MAINTBOT:
+ what = "a maintbot";
+ if (!victim->item[item])
+ CLR_BIT(victim->have2, HAS2_MAINTBOT);
+ break;
case ITEM_TRACTOR_BEAM:
what = "a tractor beam";
if (!victim->item[item])
@@ -849,6 +856,9 @@
break;
case ITEM_EMERGENCY_SHIELD:
SET_BIT(pl->have, HAS_EMERGENCY_SHIELD);
+ break;
+ case ITEM_MAINTBOT:
+ SET_BIT(pl->have2, HAS2_MAINTBOT);
break;
case ITEM_TRACTOR_BEAM:
SET_BIT(pl->have, HAS_TRACTOR_BEAM);
Index: src/server/netserver.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/netserver.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 netserver.c
--- src/server/netserver.c 2001/07/06 23:22:00 1.1.1.4
+++ src/server/netserver.c 2001/08/02 23:34:29
@@ -1393,6 +1393,41 @@
return 5 + item_count;
}
+static int
+Send_self_damage(int ind, player *pl)
+{
+ connection_t *connp = &Conn[ind];
+ unsigned sys_mask = 0;
+ int sys_count = 0;
+ int i, n;
+
+ for (i = 0; i < NUM_SYSTEMS; ++i) {
+ if (pl->damage[i] > 0.0) {
+ sys_mask |= (1 << i);
+ ++sys_count;
+ }
+ }
+
+ /* check if enough buffer space is available for the complete packet. */
+ if (connp->w.size - connp->w.len <= (5 + sys_count * sizeof(unsigned long)))
+ return 0;
+
+ /* build the header */
+ n = Packet_printf(&connp->w, "%c%u", PKT_DAMAGE, sys_mask);
+ if (n <= 0)
+ return n;
+
+ for (i = 0; i < NUM_SYSTEMS; ++i)
+ if (sys_mask & (1 << i)) {
+ unsigned long val = (unsigned long) (10.0 * pl->damage[i]);
+ val = htonl(val);
+ memcpy(connp->w.buf + connp->w.len, &val, sizeof (unsigned long));
+ connp->w.len += sizeof (unsigned long);
+ }
+
+ return 5 + (sys_count * sizeof(unsigned long));
+}
+
/*
* Send all frame data related to the player self and his HUD.
*/
@@ -1448,6 +1483,9 @@
if (n <= 0) {
return n;
}
+ n = Send_self_damage(ind, pl);
+ if (n <= 0)
+ return n;
return Send_modifiers(ind, mods);
}
Index: src/server/object.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/object.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 object.h
--- src/server/object.h 2001/07/01 18:31:28 1.1.1.3
+++ src/server/object.h 2001/08/02 23:34:29
@@ -46,6 +46,8 @@
#include "click.h"
#endif
+#include "systems.h"
+
#ifdef _WINDOWS
#include "NT/winNet.h"
#endif
@@ -110,6 +112,8 @@
#define HAS_SHOT (1U<<4)
#define HAS_BALL (1U<<3)
+/* Values for player->have2 and player->used2 fields */
+#define HAS2_MAINTBOT (1U<<0)
/*
* Weapons modifiers.
@@ -465,6 +469,8 @@
int type_ext; /* extended type info (tank, robot) */
+ DFLOAT damage[NUM_SYSTEMS];
+
DFLOAT turnspeed; /* How fast player acc-turns */
DFLOAT velocity; /* Absolute speed */
@@ -473,6 +479,9 @@
long used; /** Items you use **/
long have; /** Items you have **/
+
+ long used2; /* Extension fields */
+ long have2;
int shield_time; /* Shields if no playerShielding */
pl_fuel_t fuel; /* ship tanks and the stored fuel */
Index: src/server/player.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/player.c,v
retrieving revision 1.1.1.4
diff -u -r1.1.1.4 player.c
--- src/server/player.c 2001/07/06 23:21:59 1.1.1.4
+++ src/server/player.c 2001/08/02 23:34:29
@@ -193,6 +193,7 @@
pl->turnacc = pl->turnvel = 0.0;
memset(pl->last_keyv, 0, sizeof(pl->last_keyv));
memset(pl->prev_keyv, 0, sizeof(pl->prev_keyv));
+ memset(pl->damage, 0, sizeof(pl->damage));
pl->used &= ~USED_KILL;
if (playerStartsShielded != 0) {
@@ -428,6 +429,7 @@
pl->status = PLAYING | GRAVITY | DEF_BITS;
pl->have = DEF_HAVE;
+ pl->have2 = DEF_HAVE2;
pl->used = DEF_USED;
if (pl->item[ITEM_CLOAK] > 0) {
@@ -1850,6 +1852,9 @@
}
}
+ for (i = 0; i < NUM_SYSTEMS; ++i)
+ pl->damage[i] = 0.0;
+
pl->forceVisible = 0;
pl->shot_speed = ShotsSpeed;
pl->shot_max = ShotsMax;
@@ -1909,6 +1914,7 @@
pl->deaths++;
pl->have = DEF_HAVE;
+ pl->have2 = DEF_HAVE2;
pl->used |= DEF_USED;
pl->used &= ~(USED_KILL);
pl->used &= pl->have;
Index: src/server/robotdef.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/robotdef.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 robotdef.c
--- src/server/robotdef.c 2001/07/01 18:31:28 1.1.1.3
+++ src/server/robotdef.c 2001/08/02 23:34:29
@@ -1514,6 +1514,7 @@
case ITEM_REARSHOT: /* shoot competitors behind you */
case ITEM_MINE: /* blows others off the track */
case ITEM_ECM: /* blinded players smash into walls */
+ case ITEM_MAINTBOT:
return ROBOT_MUST_HAVE_ITEM;
case ITEM_CLOAK: /* not important in racemode */
case ITEM_LASER: /* cost too much fuel */
@@ -1559,6 +1560,7 @@
case ITEM_MINE:
case ITEM_CLOAK:
+ case ITEM_MAINTBOT:
return ROBOT_MUST_HAVE_ITEM;
case ITEM_LASER:
Index: src/server/rules.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/rules.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 rules.c
--- src/server/rules.c 2001/07/01 18:31:28 1.1.1.3
+++ src/server/rules.c 2001/08/02 23:34:29
@@ -62,6 +62,7 @@
#define MAX_HYPERJUMP 99
#define MAX_LASER 99
#define MAX_TRACTOR_BEAM 99
+#define MAX_MAINTBOTS 99
long KILLING_SHOTS = (OBJ_SHOT|OBJ_SMART_SHOT|OBJ_TORPEDO|OBJ_HEAT_SHOT|OBJ_PULSE);
long DEF_BITS = 0;
@@ -69,6 +70,7 @@
long DEF_HAVE =
(HAS_SHIELD|HAS_COMPASS|HAS_REFUEL|HAS_REPAIR|HAS_CONNECTOR
|HAS_SHOT|HAS_LASER);
+long DEF_HAVE2 = HAS2_MAINTBOT;
long DEF_USED = (HAS_SHIELD|HAS_COMPASS);
long USED_KILL =
(HAS_REFUEL|HAS_REPAIR|HAS_CONNECTOR|HAS_SHOT|HAS_LASER|HAS_ARMOR
@@ -234,6 +236,7 @@
LIMIT(World.items[ITEM_HYPERJUMP].limit, 0, MAX_HYPERJUMP);
LIMIT(World.items[ITEM_MIRROR].limit, 0, MAX_MIRROR);
LIMIT(World.items[ITEM_ARMOR].limit, 0, MAX_ARMOR);
+ LIMIT(World.items[ITEM_MAINTBOT].limit, 0, MAX_MAINTBOTS);
for (i = 0; i < NUM_ITEMS; i++) {
LIMIT(World.items[i].initial, 0, World.items[i].limit);
@@ -248,8 +251,11 @@
HAS_AUTOPILOT |
HAS_DEFLECTOR |
HAS_MIRROR |
- HAS_ARMOR);
+ HAS_ARMOR |
+ HAS_REPAIR);
+ CLR_BIT(DEF_HAVE2, HAS2_MAINTBOT);
+
if (World.items[ITEM_CLOAK].initial > 0)
SET_BIT(DEF_HAVE, HAS_CLOAKING_DEVICE);
if (World.items[ITEM_EMERGENCY_THRUST].initial > 0)
@@ -268,6 +274,8 @@
SET_BIT(DEF_HAVE, HAS_MIRROR);
if (World.items[ITEM_ARMOR].initial > 0)
SET_BIT(DEF_HAVE, HAS_ARMOR);
+ if (World.items[ITEM_MAINTBOT].initial > 0)
+ SET_BIT(DEF_HAVE2, HAS2_MAINTBOT);
}
@@ -310,6 +318,7 @@
Init_item(ITEM_EMERGENCY_SHIELD, 1, 1);
Init_item(ITEM_TRACTOR_BEAM, 1, 1);
Init_item(ITEM_AUTOPILOT, 1, 1);
+ Init_item(ITEM_MAINTBOT, 1, 1);
Set_misc_item_limits();
Index: src/server/score.h
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/score.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 score.h
--- src/server/score.h 2001/07/01 18:31:28 1.1.1.2
+++ src/server/score.h 2001/08/02 23:34:29
@@ -42,6 +42,7 @@
/* was 90 -> 2 -> 40 -> 20 -> 10 */
#define ED_LASER_HIT (-100.0*FUEL_SCALE_FACT)
/* was 120 -> 80 -> 40 -> 50 -> 60 -> 100 */
+#define ED_MAINTBOT (2.0*FUEL_SCALE_FACT) /* sic -- positive */
#define PTS_PR_PL_SHOT -5 /* Points if you get shot by a player */
Index: src/server/ship.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/ship.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 ship.c
--- src/server/ship.c 2001/07/01 18:31:28 1.1.1.1
+++ src/server/ship.c 2001/08/02 23:34:29
@@ -478,6 +478,7 @@
/* Mass is only tank + fuel */
dummy->mass = (dummy->emptymass = ShipMass) + FUEL_MASS(dummy->fuel.sum);
dummy->have = DEF_HAVE;
+ dummy->have2 = DEF_HAVE2;
dummy->used = DEF_USED;
dummy->power *= TANK_THRUST_FACT;
@@ -501,6 +502,7 @@
/* The tank uses shield and thrust */
dummy->status = (DEF_BITS & ~KILL_BITS) | PLAYING | GRAVITY | THRUSTING;
dummy->have = DEF_HAVE;
+ dummy->have2 = DEF_HAVE2;
dummy->used = (DEF_USED & ~USED_KILL & pl->have) | HAS_SHIELD;
if (playerShielding == 0) {
dummy->shield_time = 30 * FPS;
Index: src/server/shot.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/shot.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 shot.c
--- src/server/shot.c 2001/07/01 18:31:28 1.1.1.1
+++ src/server/shot.c 2001/08/02 23:34:29
@@ -46,6 +46,7 @@
#include "netserver.h"
#include "error.h"
#include "commonproto.h"
+#include "damage.h"
char shot_version[] = VERSION;
@@ -1060,6 +1061,17 @@
mv.x = mv.y = shot->acc.x = shot->acc.y = 0;
break;
}
+
+ if (pl && (pl->damage[sys_guns] > 0.0)) {
+ DFLOAT logdmg = log(pl->damage[sys_guns]);
+
+ speed /= (1.0 + (rfrac() * pl->damage[sys_guns]));
+ ldir = MOD2(ldir +
+ ((int)(rfrac() *
+ log(1.0 + pl->damage[sys_guns]) *
+ DMG_SHOT_AWRY_FACTOR)),
+ RES);
+ }
shot->vel.x = mv.x + (pl ? pl->vel.x : 0.0) + tcos(ldir) * speed;
shot->vel.y = mv.y + (pl ? pl->vel.y : 0.0) + tsin(ldir) * speed;
Index: src/server/update.c
===================================================================
RCS file: /var/src/cvsroot/xpilot/src/server/update.c,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 update.c
--- src/server/update.c 2001/07/01 18:31:28 1.1.1.3
+++ src/server/update.c 2001/08/02 23:34:29
@@ -43,6 +43,8 @@
#include "objpos.h"
#include "cannon.h"
#include "asteroid.h"
+#include "systems.h"
+#include "damage.h"
#define TURN_FUEL(acc) (0.005*FUEL_SCALE_FACT*ABS(acc))
#define TURN_SPARKS(tf) (5+((tf)>>((FUEL_SCALE_BITS)-6)))
@@ -402,6 +404,12 @@
}
}
+static int
+random_compare(const void *a, const void *b)
+{
+ return ((randomMT() % 2) ? 1 : -1);
+}
+
/********** **********
* Updating objects and the like.
*/
@@ -635,6 +643,7 @@
*/
for (i=0; i<NumPlayers; i++) {
long tf = 0;
+ DFLOAT repair_capacity;
pl = Players[i];
@@ -764,7 +773,14 @@
/*
* Compute turn
*/
- pl->turnvel += pl->turnacc;
+ if (pl->damage[sys_turn_thrusters] > 0.0) {
+ DFLOAT turnacc = pl->turnacc;
+ turnacc /= (1.0 + (rfrac() * pl->damage[sys_turn_thrusters]));
+
+ pl->turnvel += turnacc;
+ } else {
+ pl->turnvel += pl->turnacc;
+ }
/*
* turnresistance is zero: client requests linear turning behaviour
@@ -931,6 +947,11 @@
power = AFTER_BURN_POWER(power, a);
f = AFTER_BURN_FUEL(f, a);
}
+
+ if (pl->damage[sys_main_thruster] > 0.0) {
+ power /= (1.0 + (rfrac() * pl->damage[sys_main_thruster]));
+ }
+
pl->acc.x = power * tcos(pl->dir) / inert;
pl->acc.y = power * tsin(pl->dir) / inert;
Add_fuel(&(pl->fuel), (long)(-f * FUEL_SCALE_FACT)); /* Decrement fuel */
@@ -1106,9 +1127,51 @@
if (!BIT(pl->status, PAUSE)) {
update_object_speed(pl); /* New position */
+
+ if (pl->damage[sys_structure] > 0.0) {
+ DFLOAT accel = LENGTH(pl->acc.x, pl->acc.y);
+ DFLOAT F = pl->mass * accel;
+ DFLOAT F_fraction = F * rfrac() * rfrac();
+
+ if (F_fraction * pl->damage[sys_structure] >
+ DMG_HULL_STRESS_THRESHOLD) {
+
+ SET_BIT(pl->status, KILLED);
+ sprintf(msg, "%s overstressed a damaged hull", pl->name);
+ Set_message(msg);
+
+ } else {
+ pl->damage[sys_structure] *=
+ (1.0 + F_fraction / DMG_HULL_STRESS_BASE);
+ }
+ }
+
Move_player(i);
}
+ /* Do leaky tanks after Move_player so
+ leak comes from the right place */
+ if ((pl->damage[sys_tanks] > 0.0) && pl->fuel.sum) {
+ long leak = pl->damage[sys_tanks] * DMG_TANK_LEAK;
+
+ Add_fuel(&(pl->fuel), -leak);
+ Make_debris(
+ /* pos.x, pos.y */ pl->pos.x, pl->pos.y,
+ /* vel.x, vel.y */ pl->vel.x, pl->vel.y,
+ /* owner id */ pl->id,
+ /* owner team */ pl->team,
+ /* kind */ OBJ_SPARK,
+ /* mass */ THRUST_MASS,
+ /* status */ GRAVITY | OWNERIMMUNE,
+ /* color */ RED,
+ /* radius */ 8,
+ /* min,max debris */ leak / 32, leak / 32,
+ /* min,max dir */ 0, RES - 1,
+ /* min,max speed */ 1.0, 2.0,
+ /* min,max life */ 3, 12
+ );
+ }
+
if ((!BIT(pl->used, HAS_CLOAKING_DEVICE) || cloakedExhaust)
&& !BIT(pl->used, HAS_PHASING_DEVICE)) {
if (BIT(pl->status, THRUSTING))
@@ -1118,6 +1181,62 @@
}
Compute_sensor_range(pl);
+
+ /* Do repairs */
+ repair_capacity = pl->item[ITEM_MAINTBOT] * DMG_REPAIR_CAPACITY;
+
+ if (pl->damage[sys_maintenance]) {
+ repair_capacity /= (1.0 + (rfrac() * pl->damage[sys_maintenance]));
+ }
+
+ if (repair_capacity > 0.0) {
+ int damaged_systems[NUM_SYSTEMS];
+ int num_damaged_systems = 0;
+ int i;
+ int system;
+ DFLOAT fuel_needed;
+
+ for (i = 0; i < NUM_SYSTEMS; ++i)
+ if (pl->damage[i] > 0.0)
+ damaged_systems[num_damaged_systems++] = i;
+
+ /* Randomize the order in which we do repairs */
+ qsort(damaged_systems, num_damaged_systems, sizeof (int),
+ random_compare);
+
+ for (i = 0; i < num_damaged_systems - 1; ++i) {
+ DFLOAT repair_amount = repair_capacity * rfrac();
+
+ system = damaged_systems[i];
+
+ if (pl->damage[system] < repair_amount)
+ repair_amount = pl->damage[system];
+
+ fuel_needed = repair_amount * ED_MAINTBOT;
+ if (fuel_needed > pl->fuel.sum) {
+ fuel_needed = pl->fuel.sum;
+ repair_amount = fuel_needed / ED_MAINTBOT;
+ }
+
+ pl->damage[system] -= repair_amount;
+ Add_fuel(&(pl->fuel), (long)(-fuel_needed));
+
+ repair_capacity -= repair_amount;
+ }
+
+ system = damaged_systems[num_damaged_systems - 1];
+ if (pl->damage[system] < repair_capacity)
+ repair_capacity = pl->damage[system];
+
+ fuel_needed = repair_capacity * ED_MAINTBOT;
+ if (fuel_needed > pl->fuel.sum) {
+ fuel_needed = pl->fuel.sum;
+ repair_capacity = fuel_needed / ED_MAINTBOT;
+ }
+
+ pl->damage[system] -= repair_capacity;
+ Add_fuel(&(pl->fuel), (long)(-fuel_needed));
+ }
pl->used &= pl->have;
}
-------------- next part --------------
#define itemMaintbot_width 16
#define itemMaintbot_height 16
static unsigned char itemMaintbot_bits[] = {
0x00, 0x00, 0xc0, 0x01, 0x38, 0x0e, 0x04, 0x10, 0x02, 0x20, 0xc2, 0x21,
0xe2, 0x23, 0xc1, 0x41, 0x0d, 0x58, 0xff, 0x7f, 0x01, 0x40, 0xf9, 0x4d,
0x01, 0x40, 0xe9, 0x4f, 0x01, 0x40, 0x01, 0x40};
-------------- next part --------------
#ifndef XPILOT_SYSTEMS_H
# define XPILOT_SYSTEMS_H
/* Ship systems that can be damaged */
enum System {
sys_structure = 0, /* structural integrity */
sys_controls, /* responding to operator input */
sys_tanks,
sys_main_thruster,
sys_turn_thrusters,
sys_shields,
sys_guns,
sys_maintenance,
NUM_SYSTEMS
};
extern const char *sys_names[];
#endif /* XPILOT_SYSTEMS_H */
-------------- next part --------------
#include "systems.h"
const char *sys_names[] = {
"structure",
"controls",
"tanks",
"main thruster",
"turn thrusters",
"shields",
"guns",
"maintenance"
};
-------------- next part --------------
#ifndef XPILOT_DAMAGE_H
# define XPILOT_DAMAGE_H
#define DMG_TANK_EXPLOSION_THRESHOLD (5.0)
#define DMG_TANK_LEAK (32.0)
#define DMG_REPAIR_CAPACITY (0.01)
#define DMG_SHOT_AWRY_FACTOR (1.5)
#define DMG_HULL_FAILURE_THRESHOLD (5.0)
#define DMG_HULL_STRESS_THRESHOLD (1000.0)
#define DMG_HULL_STRESS_BASE (10000.0)
#endif /* XPILOT_DAMAGE_H */
More information about the Xpilot-hacks
mailing list