Removed D1X implementation of multiplayer powerup capping and added D2X code to replace this (UDP-only); Added a bunch of D2X code for general and multiplayer powerup dropping to make codes more consistent to each other; Removed MULTI_PROTO_D1X_VER and MULTI_PROTO_D1X_MINOR defines since they are not needed anymore

This commit is contained in:
zicodxx 2011-01-14 14:29:36 +01:00
parent 80597ad64f
commit 6e0ea332de
17 changed files with 591 additions and 475 deletions

View file

@ -3,6 +3,7 @@ D1X-Rebirth Changelog
20110114
--------
main/credits.c, main/menu.c, main/net_udp.c, main/scores.c: Fix compile errors introduced when merging
main/collide.c, main/fireball.c, main/gamesave.c, main/gameseq.c, main/gameseq.h, main/laser.c, main/multi.c, main/multi.h, main/multibot.c, main/net_ipx.c, main/net_udp.c, main/object.c, main/powerup.c, main/powerup.h, main/weapon.c, main/weapon.h: Removed D1X implementation of multiplayer powerup capping and added D2X code to replace this (UDP-only); Added a bunch of D2X code for general and multiplayer powerup dropping to make codes more consistent to each other; Removed MULTI_PROTO_D1X_VER and MULTI_PROTO_D1X_MINOR defines since they are not needed anymore
20110113
--------

View file

@ -1075,99 +1075,55 @@ void collide_player_and_player( object * player1, object * player2, vms_vector *
return;
}
// drop powerups in pow_count around object obj.
// special behavior:
// - POW_MISSILE_1 and POW_HOMING_AMMO_1 are split into
// POW_MISSILE_1/4 and POW_HOMING_AMMO_1/4 respectivily.
// - for single player:
// when dropping POW_VULCAN_WEAPON it gets all ammo (POW_VULCAN_AMMO),
// and no vulcan ammo is dropped.
// for multi player:
// when dropping POW_VULCAN_WEAPON it gets VULCAN_WEAPON_AMMO_AMOUNT
// ammo, and that's subtracted from the to be dropped ammo packages.
// - when dropping vulcan ammo w/o cannon, ammo is limited to 200 max
void drop_pow_count(object *obj, int *pow_count)
int maybe_drop_primary_weapon_egg(object *playerobj, int weapon_index)
{
int i, j;
int count;
int objnum;
int powerup_in_level[MAX_POWERUP_TYPES];
int weapon_flag = HAS_FLAG(weapon_index);
int powerup_num;
pow_count_level(powerup_in_level);
powerup_num = Primary_weapon_to_powerup[weapon_index];
for (j = 0; j < NUM_PLAYER_DROP_POWERUPS; j++)
{
count = pow_count[(i = player_drop_powerups[j])];
// limit powerups in D1X network games
#ifdef USE_IPX
if ((Game_mode & GM_NETWORK) &&
(Netgame.protocol.ipx.protocol_version == MULTI_PROTO_D1X_VER))
{
if (multi_allow_powerup_mask[i])
{ // only check 'important' powerups (no shield,energy,conc)
int pow_max = max(powerup_start_level[i] - powerup_in_level[i], 0);
//-killed- #ifdef NETWORK
while (count > pow_max)
{
// create dummy Net_create_objnums entries to keep objnums in sync
if (Net_create_loc >= MAX_NET_CREATE_OBJECTS)
{
return;
}
Net_create_objnums[Net_create_loc++] = -1;
count--;
}
//-killed- #else
//-killed- if (count > pow_max) count = pow_max;
//-killed- #endif
}
}
#endif
if (count > 0)
switch (i)
{
case POW_MISSILE_1:
case POW_HOMING_AMMO_1:
call_object_create_egg(obj, count / 4, OBJ_POWERUP, i + 1);
call_object_create_egg(obj, count % 4, OBJ_POWERUP, i);
break;
case POW_VULCAN_WEAPON:
if ((objnum = call_object_create_egg(obj, count, OBJ_POWERUP, POW_VULCAN_WEAPON)) != -1)
{
//added/changed on 9/5/98 by adb (from Matthew Mueller) to drop ammo in multi even with cannon
if (Game_mode & GM_MULTI) {
Objects[objnum].ctype.powerup_info.count = VULCAN_WEAPON_AMMO_AMOUNT;
} else
Objects[objnum].ctype.powerup_info.count = pow_count[POW_VULCAN_AMMO];
//end change - adb (from Matthew Mueller)
}
break;
case POW_VULCAN_AMMO:
//changed by adb on 980905 to drop ammo in multi even with cannon
if (pow_count[POW_VULCAN_WEAPON])
count -= VULCAN_WEAPON_AMMO_AMOUNT;
if (count > 0 && (pow_count[POW_VULCAN_WEAPON] == 0 || (Game_mode & GM_MULTI))) {
if (count > 200) {
count = 200;
}
call_object_create_egg(obj, (count + VULCAN_AMMO_AMOUNT - 1) / VULCAN_AMMO_AMOUNT, OBJ_POWERUP, POW_VULCAN_AMMO);
}
//end changes by adb
break;
default:
call_object_create_egg(obj, count, OBJ_POWERUP, i);
}
}
if (Players[playerobj->id].primary_weapon_flags & weapon_flag)
return call_object_create_egg(playerobj, 1, OBJ_POWERUP, powerup_num);
else
return -1;
}
void drop_player_eggs(object *player)
void maybe_drop_secondary_weapon_egg(object *playerobj, int weapon_index, int count)
{
if ((player->type == OBJ_PLAYER) || (player->type == OBJ_GHOST)) {
int pnum = player->id;
int pow_count[MAX_POWERUP_TYPES];
int weapon_flag = HAS_FLAG(weapon_index);
int powerup_num;
powerup_num = Secondary_weapon_to_powerup[weapon_index];
if (Players[playerobj->id].secondary_weapon_flags & weapon_flag) {
int i, max_count;
max_count = min(count, 3);
for (i=0; i<max_count; i++)
call_object_create_egg(playerobj, 1, OBJ_POWERUP, powerup_num);
}
}
void drop_missile_1_or_4(object *playerobj,int missile_index)
{
int num_missiles,powerup_id;
num_missiles = Players[playerobj->id].secondary_ammo[missile_index];
powerup_id = Secondary_weapon_to_powerup[missile_index];
if (num_missiles > 10)
num_missiles = 10;
call_object_create_egg(playerobj, num_missiles/4, OBJ_POWERUP, powerup_id+1);
call_object_create_egg(playerobj, num_missiles%4, OBJ_POWERUP, powerup_id);
}
void drop_player_eggs(object *playerobj)
{
if ((playerobj->type == OBJ_PLAYER) || (playerobj->type == OBJ_GHOST)) {
int pnum = playerobj->id;
int objnum;
int vulcan_ammo=0;
// Seed the random number generator so in net play the eggs will always
// drop the same way
@ -1179,9 +1135,60 @@ void drop_player_eggs(object *player)
}
#endif
player_to_pow_count(&Players[pnum], pow_count);
clip_player_pow_count(pow_count);
drop_pow_count(player, pow_count);
// If the player dies and he has powerful lasers, create the powerups here.
if (Players[pnum].laser_level >= 1)
call_object_create_egg(playerobj, Players[pnum].laser_level, OBJ_POWERUP, POW_LASER); // Note: laser_level = 0 for laser level 1.
// Drop quad laser if appropos
if (Players[pnum].flags & PLAYER_FLAGS_QUAD_LASERS)
call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_QUAD_FIRE);
if (Players[pnum].flags & PLAYER_FLAGS_CLOAKED)
call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_CLOAK);
//Drop the vulcan, gauss, and ammo
vulcan_ammo = Players[pnum].primary_ammo[VULCAN_INDEX];
if (vulcan_ammo < VULCAN_AMMO_AMOUNT)
vulcan_ammo = VULCAN_AMMO_AMOUNT; //make sure gun has at least as much as a powerup
objnum = maybe_drop_primary_weapon_egg(playerobj, VULCAN_INDEX);
if (objnum!=-1)
Objects[objnum].ctype.powerup_info.count = vulcan_ammo;
// Drop the rest of the primary weapons
maybe_drop_primary_weapon_egg(playerobj, SPREADFIRE_INDEX);
maybe_drop_primary_weapon_egg(playerobj, PLASMA_INDEX);
maybe_drop_primary_weapon_egg(playerobj, FUSION_INDEX);
// Drop the secondary weapons
// Note, proximity weapon only comes in packets of 4. So drop n/2, but a max of 3 (handled inside maybe_drop..) Make sense?
maybe_drop_secondary_weapon_egg(playerobj, PROXIMITY_INDEX, (Players[playerobj->id].secondary_ammo[PROXIMITY_INDEX])/4);
maybe_drop_secondary_weapon_egg(playerobj, SMART_INDEX, Players[playerobj->id].secondary_ammo[SMART_INDEX]);
maybe_drop_secondary_weapon_egg(playerobj, MEGA_INDEX, Players[playerobj->id].secondary_ammo[MEGA_INDEX]);
// Drop the player's missiles in packs of 1 and/or 4
drop_missile_1_or_4(playerobj,HOMING_INDEX);
drop_missile_1_or_4(playerobj,CONCUSSION_INDEX);
// If player has vulcan ammo, but no vulcan cannon, drop the ammo.
if (!(Players[playerobj->id].primary_weapon_flags & HAS_VULCAN_FLAG)) {
int amount = Players[playerobj->id].primary_ammo[VULCAN_INDEX];
if (amount > 200) {
amount = 200;
}
while (amount > 0) {
call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_VULCAN_AMMO);
amount -= VULCAN_AMMO_AMOUNT;
}
}
// Always drop a shield and energy powerup.
if (Game_mode & GM_MULTI) {
call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_SHIELD_BOOST);
call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_ENERGY);
}
}
}

View file

@ -433,6 +433,7 @@ int choose_drop_segment(void)
}
extern char PowerupsInMine[],MaxPowerupsAllowed[];
// ------------------------------------------------------------------------------------------------------
// Drop cloak powerup if in a network game.
void maybe_drop_net_powerup(int powerup_type)
@ -441,8 +442,13 @@ void maybe_drop_net_powerup(int powerup_type)
int segnum, objnum;
vms_vector new_pos;
if (Control_center_destroyed || Endlevel_sequence ||
!may_create_powerup(powerup_type))
if (Game_mode & GM_NETWORK)
{
if (PowerupsInMine[powerup_type]>=MaxPowerupsAllowed[powerup_type])
return;
}
if (Control_center_destroyed || Endlevel_sequence)
return;
segnum = choose_drop_segment();
@ -964,8 +970,7 @@ void do_explosion_sequence(object *obj)
// If dropping a weapon that the player has, drop energy instead, unless it's vulcan, in which case drop vulcan ammo.
if (del_obj->contains_type == OBJ_POWERUP)
maybe_replace_powerup_with_energy(del_obj);
if (object_create_egg(del_obj) >= 0)
pow_add_random(del_obj);
object_create_egg(del_obj);
} else if ((del_obj->type == OBJ_ROBOT) && !(Game_mode & GM_MULTI)) { // Multiplayer handled outside this code!!
robot_info *robptr = &Robot_info[del_obj->id];
if (robptr->contains_count) {
@ -974,8 +979,7 @@ void do_explosion_sequence(object *obj)
del_obj->contains_type = robptr->contains_type;
del_obj->contains_id = robptr->contains_id;
maybe_replace_powerup_with_energy(del_obj);
if (object_create_egg(del_obj) >= 0)
pow_add_random(del_obj);
object_create_egg(del_obj);
}
}
}

View file

@ -277,6 +277,20 @@ void verify_object( object * obj ) {
obj->control_type = CT_POWERUP;
obj->size = Powerup_info[obj->id].size;
if (Game_mode & GM_NETWORK)
{
if (multi_powerup_is_4pack(obj->id))
{
PowerupsInMine[obj->id-1]+=4;
MaxPowerupsAllowed[obj->id-1]+=4;
}
else
{
PowerupsInMine[obj->id]++;
MaxPowerupsAllowed[obj->id]++;
}
}
}
if ( obj->type == OBJ_WEAPON ) {

View file

@ -1243,8 +1243,6 @@ void StartNewLevelSub(int level_num, int page_in_textures)
gameseq_remove_unused_players();
count_powerup_start_level();
Game_suspended = 0;
Control_center_destroyed = 0;
@ -1289,6 +1287,24 @@ void StartNewLevelSub(int level_num, int page_in_textures)
game();
}
#ifdef NETWORK
extern char PowerupsInMine[MAX_POWERUP_TYPES], MaxPowerupsAllowed[MAX_POWERUP_TYPES];
#endif
void bash_to_shield (int i,char *s)
{
#ifdef NETWORK
int type=Objects[i].id;
#endif
#ifdef NETWORK
PowerupsInMine[type]=MaxPowerupsAllowed[type]=0;
#endif
Objects[i].id = POW_SHIELD_BOOST;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
}
//called when the player is starting a new level for normal game model
void StartNewLevel(int level_num)
{

View file

@ -116,4 +116,6 @@ extern void DoEndLevelScoreGlitz(int network);
extern int MaxNumNetPlayers;
extern int NumNetPlayerPositions;
void bash_to_shield(int, char *);
#endif /* _GAMESEQ_H */

View file

@ -1457,14 +1457,12 @@ void create_smart_children(object *objp)
#define MEGA_GUN 7
int Missile_gun=0;
int Missile_gun=0, Proximity_dropped = 0;
// -------------------------------------------------------------------------------------------
//changed on 9/16/98 by adb to distinguish between drop bomb and secondary fire
void do_missile_firing(int drop_bomb)
{
static int proximity = 0;
int weapon = (drop_bomb) ? PROXIMITY_INDEX : Secondary_weapon;
Assert(weapon < MAX_SECONDARY_WEAPONS);
@ -1488,10 +1486,10 @@ void do_missile_firing(int drop_bomb)
break;
case PROXIMITY_INDEX:
proximity ++;
if (proximity == 4)
Proximity_dropped ++;
if (Proximity_dropped == 4)
{
proximity = 0;
Proximity_dropped = 0;
#ifdef NETWORK
maybe_drop_net_powerup(POW_PROXIMITY_WEAPON);
#endif

View file

@ -74,8 +74,10 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
#define vm_angvec_zero(v) (v)->p=(v)->b=(v)->h=0
void reset_player_object(void); // In object.c but not in object.h
void drop_player_eggs(object *player); // from collide.c
void drop_player_eggs(object *playerobj); // from collide.c
void StartLevel(void); // From gameseq.c
void multi_powcap_cap_objects();
void multi_powcap_adjust_remote_cap(int pnum);
//
// Global variables
@ -126,6 +128,9 @@ int Network_send_object_mode = 0; // What type of objects are we sending, static
int Network_send_objnum = -1; // What object are we sending next?
int Network_rejoined = 0; // Did WE rejoin this game?
int Network_new_game = 0; // Is this the first level of a new game?
int Network_sending_extras=0;
int VerifyPlayerJoined=-1; // Player (num) to enter game before any ingame/extra stuff is being sent
int Player_joining_extras=-1; // This is so we know who to send 'latecomer' packets to.
int Network_player_added = 0; // Is this a new player or a returning player?
//added 02/26/99 Matt Mueller - reactor kill stats
@ -133,9 +138,6 @@ short reactor_kills[MAX_NUM_NET_PLAYERS];
int reactor_kills_total;
//end addition -MM
uint multi_allow_powerup;
uint multi_got_pow_count;
ushort my_segments_checksum = 0;
netgame_info Netgame;
@ -146,6 +148,8 @@ bitmap_index multi_player_textures[MAX_NUM_NET_PLAYERS][N_PLAYER_SHIP_TEXTURES];
char RefuseThisPlayer=0,WaitForRefuseAnswer=0,RefuseTeam,RefusePlayerName[12];
fix64 RefuseTimeLimit=0;
char PowerupsInMine[MAX_POWERUP_TYPES],MaxPowerupsAllowed[MAX_POWERUP_TYPES];
int message_length[MULTI_MAX_TYPE+1] = {
25, // POSITION
3, // REAPPEAR
@ -184,8 +188,7 @@ int message_length[MULTI_MAX_TYPE+1] = {
2+4, //RESTORE_GAME (ubyte slot, uint id) // obsolete
-1, // MULTI_REQ_PLAYER - NEVER USED
-1, // MULTI_SEND_PLAYER - NEVER USED
19, // PLAYER_POWERUP_COUNT
19, // START_POWERUP_COUNT
MAX_POWERUP_TYPES+1, // MULTI_POWCAP_UPDATE
};
void multi_reset_player_object(object *objp);
@ -371,6 +374,12 @@ multi_endlevel_score(void)
// Reset keys
Players[i].flags &= ~(PLAYER_FLAGS_BLUE_KEY | PLAYER_FLAGS_RED_KEY | PLAYER_FLAGS_GOLD_KEY);
}
for (i=0;i<MAX_POWERUP_TYPES;i++)
{
MaxPowerupsAllowed[i]=0;
PowerupsInMine[i]=0;
}
}
int
@ -421,8 +430,6 @@ multi_new_game(void)
game_disable_cheats();
Player_exploded = 0;
Dead_player_camera = 0;
multi_allow_powerup = NETFLAG_DOPOWERUP;
multi_got_pow_count = 0;
}
void
@ -752,6 +759,7 @@ multi_leave_game(void)
{
Net_create_loc = 0;
multi_send_position(Players[Player_num].objnum);
multi_powcap_cap_objects();
drop_player_eggs(ConsoleObject);
multi_send_player_explode(MULTI_PLAYER_DROP);
}
@ -1369,39 +1377,6 @@ multi_do_reappear(char *buf)
create_player_appearance_effect(&Objects[objnum]);
}
void
multi_do_powerup_count(char *buf)
{
int pnum = buf[1];
int count;
int pow_count[MAX_POWERUP_TYPES];
int i, pow;
memset(pow_count, 0, sizeof(pow_count));
count = 2;
for (i = 0; i < NUM_PLAYER_DROP_POWERUPS; i++)
{
pow = player_drop_powerups[i];
if (pow == POW_VULCAN_AMMO)
{
pow_count[pow] = *((short *)&buf[count]); count += 2;
}
else
pow_count[pow] = buf[count++];
}
if ((multi_got_pow_count & (1 << pnum)))
return; // already got pow_count from this player
if (buf[0] == MULTI_START_POWERUP_COUNT)
{
memset(powerup_start_level, 0, sizeof(powerup_start_level));
multi_got_pow_count = -1;
}
else
multi_got_pow_count |= (1 << pnum);
pow_add_level_pow_count(pow_count);
}
void
multi_do_player_explode(char *buf)
{
@ -1446,6 +1421,8 @@ multi_do_player_explode(char *buf)
Players[pnum].primary_ammo[VULCAN_INDEX] = GET_INTEL_SHORT(buf + count); count += 2;
Players[pnum].flags = GET_INTEL_INT(buf + count); count += 4;
multi_powcap_adjust_remote_cap (pnum);
objp = Objects+Players[pnum].objnum;
// objp->phys_info.velocity = *(vms_vector *)(buf+16); // 12 bytes
@ -1611,6 +1588,23 @@ multi_do_remobj(char *buf)
Network_send_objnum = -1;
}
if (Objects[local_objnum].type==OBJ_POWERUP)
if (Game_mode & GM_NETWORK)
{
if (multi_powerup_is_4pack (Objects[local_objnum].id))
{
if (PowerupsInMine[Objects[local_objnum].id-1]-4<0)
PowerupsInMine[Objects[local_objnum].id-1]=0;
else
PowerupsInMine[Objects[local_objnum].id-1]-=4;
}
else
{
if (PowerupsInMine[Objects[local_objnum].id]>0)
PowerupsInMine[Objects[local_objnum].id]--;
}
}
Objects[local_objnum].flags |= OF_SHOULD_BE_DEAD; // quick and painless
}
@ -1790,9 +1784,6 @@ multi_do_create_powerup(char *buf)
new_pos.z = (fix)SWAPINT((int)new_pos.z);
#endif
if (!may_create_powerup(powerup_type))
return;
Net_create_loc = 0;
my_objnum = call_object_create_egg(&Objects[Players[pnum].objnum], 1, OBJ_POWERUP, powerup_type);
@ -1814,6 +1805,14 @@ multi_do_create_powerup(char *buf)
map_objnum_local_to_remote(my_objnum, objnum, pnum);
object_create_explosion(segnum, &new_pos, i2f(5), VCLIP_POWERUP_DISAPPEARANCE);
if (Game_mode & GM_NETWORK)
{
if (multi_powerup_is_4pack((int)powerup_type))
PowerupsInMine[(int)(powerup_type-1)]+=4;
else
PowerupsInMine[(int)powerup_type]++;
}
}
void
@ -2050,9 +2049,8 @@ multi_process_data(char *buf, int len)
if (!Endlevel_sequence) multi_do_create_robot_powerups(buf); break;
case MULTI_HOSTAGE_DOOR:
if (!Endlevel_sequence) multi_do_hostage_door_status(buf); break;
case MULTI_PLAYER_POWERUP_COUNT:
case MULTI_START_POWERUP_COUNT:
if (!Endlevel_sequence) multi_do_powerup_count(buf); break;
case MULTI_POWCAP_UPDATE:
if (!Endlevel_sequence) multi_do_powcap_update(buf); break;
default:
Int3();
}
@ -2163,42 +2161,6 @@ multi_send_endlevel_start(int secret)
}
}
void
multi_send_powerup_count(char type, int *pow_count)
{
int i, pow;
int count = 0;
multibuf[count++] = type;
multibuf[count++] = Player_num;
for (i = 0; i < NUM_PLAYER_DROP_POWERUPS; i++)
{
pow = player_drop_powerups[i];
if (pow == POW_VULCAN_AMMO)
{
*((short *)&multibuf[count]) = pow_count[pow]; count += 2;
}
else
multibuf[count++] = pow_count[pow];
}
multi_send_data(multibuf, count, 1);
}
void
multi_send_player_powerup_count()
{
int pow_count[MAX_POWERUP_TYPES];
player_to_pow_count(&Players[Player_num], pow_count);
multi_send_powerup_count(MULTI_PLAYER_POWERUP_COUNT, pow_count);
}
void
multi_send_start_powerup_count()
{
multi_send_powerup_count(MULTI_START_POWERUP_COUNT, powerup_start_level);
}
void
multi_send_player_explode(char type)
{
@ -2262,6 +2224,152 @@ multi_send_player_explode(char type)
multi_strip_robots(Player_num);
}
extern ubyte Secondary_weapon_to_powerup[], Primary_weapon_to_powerup[];
extern int Proximity_dropped;
/*
* Powerup capping: Keep track of how many powerups are in level and kill these which would exceed initial limit.
* NOTE: Code from D2 - never been in D1, so disable in IPX
*/
// Count the initial amount of Powerups in the level
void multi_powcap_count_powerups_in_mine(void)
{
int i;
for (i=0;i<MAX_POWERUP_TYPES;i++)
PowerupsInMine[i]=0;
for (i=0;i<=Highest_object_index;i++)
{
if (Objects[i].type==OBJ_POWERUP)
{
if (multi_powerup_is_4pack(Objects[i].id))
PowerupsInMine[Objects[i].id-1]+=4;
else
PowerupsInMine[Objects[i].id]++;
}
}
}
// We want to drop something. Kill every Powerup which exceeds the level limit
void multi_powcap_cap_objects()
{
char type;
int index;
if (multi_protocol == MULTI_PROTO_IPX)
return;
if (!(Game_mode & GM_NETWORK))
return;
Players[Player_num].secondary_ammo[PROXIMITY_INDEX]+=Proximity_dropped;
Proximity_dropped=0;
for (index=0;index<MAX_PRIMARY_WEAPONS;index++)
{
type=Primary_weapon_to_powerup[index];
if (PowerupsInMine[(int)type]>=MaxPowerupsAllowed[(int)type])
if(Players[Player_num].primary_weapon_flags & (1 << index))
{
con_printf(CON_NORMAL,"PIM=%d MPA=%d\n",PowerupsInMine[(int)type],MaxPowerupsAllowed[(int)type]);
con_printf(CON_NORMAL,"Killing a primary cuz there's too many! (%d)\n",type);
Players[Player_num].primary_weapon_flags&=(~(1 << index));
}
}
Players[Player_num].secondary_ammo[2]/=4;
for (index=0;index<MAX_SECONDARY_WEAPONS;index++)
{
type=Secondary_weapon_to_powerup[index];
if ((Players[Player_num].secondary_ammo[index]+PowerupsInMine[(int)type])>MaxPowerupsAllowed[(int)type])
{
if (MaxPowerupsAllowed[(int)type]-PowerupsInMine[(int)type]<0)
Players[Player_num].secondary_ammo[index]=0;
else
Players[Player_num].secondary_ammo[index]=(MaxPowerupsAllowed[(int)type]-PowerupsInMine[(int)type]);
con_printf(CON_NORMAL,"Hey! I killed secondary type %d because PIM=%d MPA=%d\n",type,PowerupsInMine[(int)type],MaxPowerupsAllowed[(int)type]);
}
}
Players[Player_num].secondary_ammo[2]*=4;
if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS)
if (PowerupsInMine[POW_QUAD_FIRE]+1 > MaxPowerupsAllowed[POW_QUAD_FIRE])
Players[Player_num].flags&=(~PLAYER_FLAGS_QUAD_LASERS);
if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)
if (PowerupsInMine[POW_CLOAK]+1 > MaxPowerupsAllowed[POW_CLOAK])
Players[Player_num].flags&=(~PLAYER_FLAGS_CLOAKED);
}
// Adds players inventory to multi cap
void multi_powcap_adjust_cap_for_player(int pnum)
{
char type;
int index;
if (!(Game_mode & GM_NETWORK))
return;
for (index=0;index<MAX_PRIMARY_WEAPONS;index++)
{
type=Primary_weapon_to_powerup[index];
if (Players[pnum].primary_weapon_flags & (1 << index))
MaxPowerupsAllowed[(int)type]++;
}
for (index=0;index<MAX_SECONDARY_WEAPONS;index++)
{
type=Secondary_weapon_to_powerup[index];
MaxPowerupsAllowed[(int)type]+=Players[pnum].secondary_ammo[index];
}
if (Players[pnum].flags & PLAYER_FLAGS_QUAD_LASERS)
MaxPowerupsAllowed[POW_QUAD_FIRE]++;
if (Players[pnum].flags & PLAYER_FLAGS_CLOAKED)
MaxPowerupsAllowed[POW_CLOAK]++;
}
void multi_powcap_adjust_remote_cap(int pnum)
{
char type;
int index;
if (!(Game_mode & GM_NETWORK))
return;
for (index=0;index<MAX_PRIMARY_WEAPONS;index++)
{
type=Primary_weapon_to_powerup[index];
if (Players[pnum].primary_weapon_flags & (1 << index))
PowerupsInMine[(int)type]++;
}
for (index=0;index<MAX_SECONDARY_WEAPONS;index++)
{
type=Secondary_weapon_to_powerup[index];
if (index==2) // PROX? Those bastards...
PowerupsInMine[(int)type]+=(Players[pnum].secondary_ammo[index]/4);
else
PowerupsInMine[(int)type]+=Players[pnum].secondary_ammo[index];
}
if (Players[pnum].flags & PLAYER_FLAGS_QUAD_LASERS)
PowerupsInMine[POW_QUAD_FIRE]++;
if (Players[pnum].flags & PLAYER_FLAGS_CLOAKED)
PowerupsInMine[POW_CLOAK]++;
}
void
multi_send_message(void)
{
@ -2358,6 +2466,22 @@ multi_send_remobj(int objnum)
sbyte obj_owner;
short remote_objnum;
if (Objects[objnum].type==OBJ_POWERUP && (Game_mode & GM_NETWORK))
{
if (multi_powerup_is_4pack (Objects[objnum].id))
{
if (PowerupsInMine[Objects[objnum].id-1]-4<0)
PowerupsInMine[Objects[objnum].id-1]=0;
else
PowerupsInMine[Objects[objnum].id-1]-=4;
}
else
{
if (PowerupsInMine[Objects[objnum].id]>0)
PowerupsInMine[Objects[objnum].id]--;
}
}
multibuf[0] = (char)MULTI_REMOVE_OBJECT;
remote_objnum = objnum_local_to_remote((short)objnum, &obj_owner);
@ -2479,6 +2603,14 @@ multi_send_create_powerup(int powerup_type, int segnum, int objnum, vms_vector *
multi_send_position(Players[Player_num].objnum);
if (Game_mode & GM_NETWORK)
{
if (multi_powerup_is_4pack(powerup_type))
PowerupsInMine[powerup_type-1]+=4;
else
PowerupsInMine[powerup_type]++;
}
multibuf[count] = MULTI_CREATE_POWERUP; count += 1;
multibuf[count] = Player_num; count += 1;
multibuf[count] = powerup_type; count += 1;
@ -2657,6 +2789,12 @@ multi_prep_level(void)
multi_set_robot_ai(); // Set all Robot AI to types we can cope with
}
if (Game_mode & GM_NETWORK)
{
multi_powcap_adjust_cap_for_player(Player_num);
multi_send_powcap_update();
}
inv_count = 0;
cloak_count = 0;
for (i=0; i<=Highest_object_index; i++)
@ -2681,31 +2819,33 @@ multi_prep_level(void)
if (Objects[i].type == OBJ_POWERUP)
{
if (Objects[i].id == POW_EXTRA_LIFE)
if (Objects[i].id == POW_EXTRA_LIFE)
{
Objects[i].id = POW_INVULNERABILITY;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
if (!(Netgame.AllowedItems & NETFLAG_DOINVUL))
{
Objects[i].id = POW_SHIELD_BOOST;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
}
else
{
Objects[i].id = POW_INVULNERABILITY;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
}
}
if ((multi_allow_powerup & multi_allow_powerup_mask[Objects[i].id]) != multi_allow_powerup_mask[Objects[i].id]) {
Objects[i].id = POW_SHIELD_BOOST;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
}
if (Game_mode & GM_MULTI_COOP)
continue;
if ((Objects[i].id >= POW_KEY_BLUE) && (Objects[i].id <= POW_KEY_GOLD))
{
Objects[i].id = POW_SHIELD_BOOST;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
}
if (!(Game_mode & GM_MULTI_COOP))
if ((Objects[i].id >= POW_KEY_BLUE) && (Objects[i].id <= POW_KEY_GOLD))
{
Objects[i].id = POW_SHIELD_BOOST;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
}
if (Objects[i].id == POW_INVULNERABILITY) {
if (inv_count >= 3) {
if (inv_count >= 3 || (!(Netgame.AllowedItems & NETFLAG_DOINVUL))) {
Objects[i].id = POW_SHIELD_BOOST;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
@ -2714,13 +2854,38 @@ multi_prep_level(void)
}
if (Objects[i].id == POW_CLOAK) {
if (cloak_count >= 3) {
if (cloak_count >= 3 || (!(Netgame.AllowedItems & NETFLAG_DOCLOAK))) {
Objects[i].id = POW_SHIELD_BOOST;
Objects[i].rtype.vclip_info.vclip_num = Powerup_info[Objects[i].id].vclip_num;
Objects[i].rtype.vclip_info.frametime = Vclip[Objects[i].rtype.vclip_info.vclip_num].frame_time;
} else
cloak_count++;
}
if (Objects[i].id == POW_FUSION_WEAPON && !(Netgame.AllowedItems & NETFLAG_DOFUSION))
bash_to_shield (i,"fusion");
if (Objects[i].id == POW_MEGA_WEAPON && !(Netgame.AllowedItems & NETFLAG_DOMEGA))
bash_to_shield (i,"mega");
if (Objects[i].id == POW_SMARTBOMB_WEAPON && !(Netgame.AllowedItems & NETFLAG_DOSMART))
bash_to_shield (i,"smartmissile");
if (Objects[i].id == POW_VULCAN_WEAPON && !(Netgame.AllowedItems & NETFLAG_DOVULCAN))
bash_to_shield (i,"vulcan");
if (Objects[i].id == POW_PLASMA_WEAPON && !(Netgame.AllowedItems & NETFLAG_DOPLASMA))
bash_to_shield (i,"plasma");
if (Objects[i].id == POW_PROXIMITY_WEAPON && !(Netgame.AllowedItems & NETFLAG_DOPROXIM))
bash_to_shield (i,"proximity");
if (Objects[i].id==POW_VULCAN_AMMO && (!(Netgame.AllowedItems & NETFLAG_DOVULCAN)))
bash_to_shield(i,"vulcan ammo");
if (Objects[i].id == POW_SPREADFIRE_WEAPON && !(Netgame.AllowedItems & NETFLAG_DOSPREAD))
bash_to_shield (i,"spread");
if (Objects[i].id == POW_LASER && !(Netgame.AllowedItems & NETFLAG_DOLASER))
bash_to_shield (i,"Laser powerup");
if (Objects[i].id == POW_HOMING_AMMO_1 && !(Netgame.AllowedItems & NETFLAG_DOHOMING))
bash_to_shield (i,"Homing");
if (Objects[i].id == POW_HOMING_AMMO_4 && !(Netgame.AllowedItems & NETFLAG_DOHOMING))
bash_to_shield (i,"Homing");
if (Objects[i].id == POW_QUAD_FIRE && !(Netgame.AllowedItems & NETFLAG_DOQUAD))
bash_to_shield (i,"Quad Lasers");
}
}
@ -2731,16 +2896,6 @@ multi_prep_level(void)
ConsoleObject->control_type = CT_FLYING;
reset_player_object();
multi_got_pow_count = 0;
#ifdef USE_IPX
// send player powerups (assumes sync already send)
if ((Game_mode & GM_NETWORK) &&
Netgame.protocol.ipx.protocol_version == MULTI_PROTO_D1X_VER &&
!Network_rejoined)
multi_send_player_powerup_count();
#endif
}
int multi_level_sync(void)
@ -2866,6 +3021,45 @@ void change_playernum_to( int new_Player_num )
Player_num = new_Player_num;
}
void multi_send_powcap_update ()
{
int i;
if (multi_protocol == MULTI_PROTO_IPX)
return;
multibuf[0]=MULTI_POWCAP_UPDATE;
for (i=0;i<MAX_POWERUP_TYPES;i++)
multibuf[i+1]=MaxPowerupsAllowed[i];
multi_send_data(multibuf, MAX_POWERUP_TYPES+1, 1);
}
void multi_do_powcap_update (char *buf)
{
int i;
if (multi_protocol == MULTI_PROTO_IPX)
return;
for (i=0;i<MAX_POWERUP_TYPES;i++)
if (buf[i+1]>MaxPowerupsAllowed[i])
MaxPowerupsAllowed[i]=buf[i+1];
}
#define POWERUPADJUSTS 2
int PowerupAdjustMapping[]={11,19};
int multi_powerup_is_4pack (int id)
{
int i;
for (i=0;i<POWERUPADJUSTS;i++)
if (id==PowerupAdjustMapping[i])
return (1);
return (0);
}
void multi_add_lifetime_kills ()
{
// This function adds a kill to lifetime stats of this player

View file

@ -68,9 +68,6 @@ extern int multi_protocol; // set and determinate used protocol
// 3 Descent II Shareware
// 4 Descent II Commercial
#define MULTI_PROTO_VERSION 2
// these two defines should become obsolete due to strict version checking in UDP
#define MULTI_PROTO_D1X_VER 7 // Increment everytime we change networking features - based on ubyte, must never be > 255
#define MULTI_PROTO_D1X_MINOR 1 //Incrementing this seems the only way possible. Still stays backwards compitible.
// PROTOCOL VARIABLES AND DEFINES - END
@ -114,10 +111,9 @@ extern int multi_protocol; // set and determinate used protocol
#define MULTI_REQ_PLAYER 35 // NEVER USED
#define MULTI_SEND_PLAYER 36 // NEVER USED
#define MULTI_PLAYER_POWERUP_COUNT 37
#define MULTI_START_POWERUP_COUNT 38
#define MULTI_POWCAP_UPDATE 37
#define MULTI_MAX_TYPE 38
#define MULTI_MAX_TYPE 37
#define MAX_MULTI_MESSAGE_LEN 90 //didn't change it, just moved it up
@ -209,8 +205,6 @@ void multi_send_audio_taunt(int taunt_num);
void multi_send_score(void);
void multi_send_trigger(int trigger);
void multi_send_hostage_door_status(int wallnum);
void multi_send_player_powerup_count();
void multi_send_start_powerup_count();
void multi_endlevel_score(void);
void multi_consistency_error(int reset);
@ -254,6 +248,9 @@ extern int Network_send_object_mode;
extern int Network_send_objnum;
extern int Network_rejoined;
extern int Network_new_game;
extern int Network_sending_extras;
extern int VerifyPlayerJoined;
extern int Player_joining_extras;
extern int Network_player_added;
extern int message_length[MULTI_MAX_TYPE+1];
@ -295,6 +292,7 @@ extern int multi_sending_message;
extern int multi_defining_message;
extern int multi_message_input_sub(int key);
extern void multi_send_message_start();
extern int multi_powerup_is_4pack(int);
extern void multi_message_feedback();
extern int control_invul_time;
@ -316,13 +314,17 @@ int multi_i_am_master(void);
int multi_who_is_master(void);
void change_playernum_to(int new_pnum);
// Multiplayer powerup capping
extern void multi_powcap_count_powerups_in_mine(void);
extern void multi_powcap_cap_objects();
extern void multi_do_powcap_update();
extern void multi_send_powcap_update();
// Globals for protocol-bound Refuse-functions
extern char RefuseThisPlayer,WaitForRefuseAnswer,RefuseTeam,RefusePlayerName[12];
extern fix64 RefuseTimeLimit;
#define REFUSE_INTERVAL (F1_0*8)
extern uint multi_allow_powerup;
extern struct netgame_info Netgame;
/*

View file

@ -1044,8 +1044,6 @@ multi_do_create_robot_powerups(char *buf)
if (egg_objnum == -1)
return; // Object buffer full
pow_add_random(&del_obj);
// Assert(egg_objnum > -1);
Assert((Net_create_loc > 0) && (Net_create_loc <= MAX_ROBOT_POWERUPS));
@ -1125,7 +1123,6 @@ multi_drop_robot_powerups(int objnum)
if (egg_objnum >= 0) {
// Transmit the object creation to the other players
multi_send_create_robot_powerups(del_obj);
pow_add_random(del_obj);
}
}

View file

@ -92,6 +92,8 @@ IPX_sequence_packet IPX_Seq;
extern obj_position Player_init[MAX_PLAYERS];
extern void game_disable_cheats();
int net_ipx_wait_for_snyc();
extern char MaxPowerupsAllowed[MAX_POWERUP_TYPES];
extern char PowerupsInMine[MAX_POWERUP_TYPES];
/* General IPX functions - START */
ubyte broadcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@ -426,7 +428,7 @@ void net_ipx_send_sequence_packet(IPX_sequence_packet seq, ubyte *server, ubyte
tmps = INTEL_SHORT(seq.player.protocol.ipx.socket);
memcpy(&(out_buffer[loc]), &tmps, 2); loc += 2;
out_buffer[loc] = seq.player.connected; loc++;
out_buffer[loc] = MULTI_PROTO_D1X_MINOR; loc++;
out_buffer[loc] = 1; loc++; // 1 was MULTI_PROTO_D1X_MINOR
if (net_address != NULL)
ipxdrv_send_packet_data( out_buffer, loc, server, node, net_address);
@ -563,7 +565,13 @@ net_ipx_init(void)
// So you want to play a netgame, eh? Let's a get a few things
// straight
int save_pnum = Player_num;
int save_pnum = Player_num, t;
for (t=0;t<MAX_POWERUP_TYPES;t++)
{
MaxPowerupsAllowed[t]=0;
PowerupsInMine[t]=0;
}
memset(&Netgame, 0, sizeof(netgame_info));
memset(&IPX_Seq, 0, sizeof(IPX_sequence_packet));
@ -2584,7 +2592,6 @@ void net_ipx_read_sync_packet( ubyte * data )
if (data) { // adb: master does have this info
Netgame.PacketsPerSec = 10;
}
multi_allow_powerup = NETFLAG_DOPOWERUP;
Network_status = NETSTAT_PLAYING;
multi_sort_kill_list();

View file

@ -84,6 +84,7 @@ void net_udp_noloss_got_ack(ubyte *data, int data_len);
void net_udp_noloss_init_mdata_queue(void);
void net_udp_noloss_clear_mdata_got(ubyte player_num);
void net_udp_noloss_process_queue(fix64 time);
void net_udp_send_extras ();
extern void game_disable_cheats();
// Variables
@ -102,6 +103,8 @@ struct _sockaddr GBcast; // global Broadcast address clients and hosts will use
struct _sockaddr GMcast_v6; // same for IPv6-only
#endif
extern obj_position Player_init[MAX_PLAYERS];
extern char MaxPowerupsAllowed[MAX_POWERUP_TYPES];
extern char PowerupsInMine[MAX_POWERUP_TYPES];
/* General UDP functions - START */
// Resolve address
@ -735,6 +738,7 @@ void net_udp_list_join_game()
change_playernum_to(1);
N_players = 0;
Network_send_objects = 0;
Network_sending_extras=0;
Network_rejoined=0;
Network_status = NETSTAT_BROWSING; // We are looking at a game menu
@ -803,7 +807,7 @@ void net_udp_init()
// So you want to play a netgame, eh? Let's a get a few things
// straight
int save_pnum = Player_num;
int save_pnum = Player_num, t;
#ifdef _WIN32
{
@ -823,6 +827,12 @@ void net_udp_init()
game_disable_cheats();
for (t=0;t<MAX_POWERUP_TYPES;t++)
{
MaxPowerupsAllowed[t]=0;
PowerupsInMine[t]=0;
}
memset(&Netgame, 0, sizeof(netgame_info));
memset(&UDP_Seq, 0, sizeof(UDP_sequence_packet));
memset(&UDP_MData, 0, sizeof(UDP_mdata_info));
@ -983,6 +993,9 @@ net_udp_disconnect_player(int playernum)
Players[playernum].connected = CONNECT_DISCONNECTED;
Netgame.players[playernum].connected = CONNECT_DISCONNECTED;
if (VerifyPlayerJoined==playernum)
VerifyPlayerJoined=-1;
if (Network_status == NETSTAT_PLAYING)
{
multi_make_player_ghost(playernum);
@ -1071,7 +1084,7 @@ void net_udp_welcome_player(UDP_sequence_packet *their)
return;
}
if (Network_send_objects)
if (Network_send_objects || Network_sending_extras)
{
// Ignore silently, we're already responding to someone and we can't
// do more than one person at a time. If we don't dump them they will
@ -1321,7 +1334,9 @@ void net_udp_stop_resync(UDP_sequence_packet *their)
(!stricmp(UDP_sync_player.player.callsign, their->player.callsign)) )
{
Network_send_objects = 0;
Network_sending_extras=0;
Network_rejoined=0;
Player_joining_extras=-1;
Network_send_objnum = -1;
}
}
@ -1431,6 +1446,9 @@ void net_udp_send_objects(void)
Network_send_objects = 0;
obj_count = 0;
Network_sending_extras=10; // start to send extras
VerifyPlayerJoined = Player_joining_extras = player_num;
return;
} // mode == 1;
} // i > Highest_object_index
@ -1557,7 +1575,9 @@ void net_udp_send_rejoin_sync(int player_num)
// have to stop and try again after the level.
net_udp_dump_player(UDP_sync_player.player.protocol.udp.addr, DUMP_ENDLEVEL);
Network_send_objects = 0;
Network_sending_extras=0;
return;
}
@ -1597,6 +1617,31 @@ void net_udp_send_rejoin_sync(int player_num)
return;
}
void net_udp_resend_sync_due_to_packet_loss()
{
int i,j;
if (!multi_i_am_master())
return;
net_udp_update_netgame();
// Fill in the kill list
for (j=0; j<MAX_PLAYERS; j++)
{
for (i=0; i<MAX_PLAYERS;i++)
Netgame.kills[j][i] = kill_matrix[j][i];
Netgame.killed[j] = Players[j].net_killed_total;
Netgame.player_kills[j] = Players[j].net_kills_total;
Netgame.player_score[j] = Players[j].score;
}
Netgame.level_time = Players[Player_num].time_level;
Netgame.monitor_vector = net_udp_create_monitor_vector();
net_udp_send_game_info(UDP_sync_player.player.protocol.udp.addr, UPID_SYNC);
}
char * net_udp_get_player_name( int objnum )
{
if ( objnum < 0 ) return NULL;
@ -2972,8 +3017,6 @@ void net_udp_read_sync_packet( ubyte * data, int data_len, struct _sockaddr send
Objects[Players[Player_num].objnum].type = OBJ_PLAYER;
multi_allow_powerup = NETFLAG_DOPOWERUP;
Network_status = NETSTAT_PLAYING;
multi_sort_kill_list();
}
@ -3491,6 +3534,9 @@ void net_udp_leave_game()
if ((multi_i_am_master()))
{
while (Network_sending_extras>1 && Player_joining_extras!=-1)
net_udp_send_extras();
Netgame.numplayers = 0;
nsave=N_players;
N_players=0;
@ -3688,8 +3734,12 @@ void net_udp_do_frame(int force, int listen)
{
net_udp_timeout_check(time);
net_udp_listen();
if (VerifyPlayerJoined!=-1 && !(FrameCount & 63))
net_udp_resend_sync_due_to_packet_loss(); // This will resend to UDP_sync_player
if (Network_send_objects)
net_udp_send_objects();
if (Network_sending_extras && VerifyPlayerJoined==-1)
net_udp_send_extras();
}
PacketUrgent = 0;
@ -4182,6 +4232,12 @@ void net_udp_read_pdata_short_packet(UDP_frame_info *pd)
TheirPlayernum = pd->Player_num;
TheirObjnum = Players[pd->Player_num].objnum;
if (VerifyPlayerJoined!=-1 && TheirPlayernum==VerifyPlayerJoined)
{
// Hurray! Someone really really got in the game (I think).
VerifyPlayerJoined=-1;
}
if (!multi_quit_game && (TheirPlayernum >= N_players))
{
if (Network_status!=NETSTAT_WAITING)
@ -4432,6 +4488,18 @@ int net_udp_get_new_player_num (UDP_sequence_packet *their)
}
}
void net_udp_send_extras ()
{
Assert (Player_joining_extras>-1);
if (Network_sending_extras==10)
multi_send_powcap_update();
Network_sending_extras--;
if (!Network_sending_extras)
Player_joining_extras=-1;
}
static int show_game_rules_handler(window *wind, d_event *event, netgame_info *netgame)
{
int k;

View file

@ -1298,7 +1298,7 @@ void set_camera_pos(vms_vector *camera_pos, object *objp)
}
}
extern void drop_player_eggs(object *objp);
extern void drop_player_eggs(object *playerobj);
extern int get_explosion_vclip(object *obj,int stage);
// ------------------------------------------------------------------------------------------------------------------
@ -1365,14 +1365,18 @@ void dead_player_frame(void)
HUD_init_message(HM_DEFAULT, TXT_SHIP_DESTROYED_0);
Player_exploded = 1;
drop_player_eggs(ConsoleObject);
Player_eggs_dropped = 1;
#ifdef NETWORK
if (Game_mode & GM_MULTI)
{
multi_send_player_explode(MULTI_PLAYER_EXPLODE);
}
#endif
#ifdef NETWORK
if (Game_mode & GM_NETWORK)
multi_powcap_cap_objects();
#endif
drop_player_eggs(ConsoleObject);
Player_eggs_dropped = 1;
#ifdef NETWORK
if (Game_mode & GM_MULTI)
{
multi_send_player_explode(MULTI_PLAYER_EXPLODE);
}
#endif
explode_badass_player(ConsoleObject);
@ -1393,21 +1397,25 @@ void dead_player_frame(void)
}
if (Death_sequence_aborted)
{
if (!Player_eggs_dropped)
{
drop_player_eggs(ConsoleObject);
Player_eggs_dropped = 1;
#ifdef NETWORK
if (Game_mode & GM_MULTI)
{
multi_send_player_explode(MULTI_PLAYER_EXPLODE);
}
#endif
}
DoPlayerDead(); //kill_player();
}
if (Death_sequence_aborted)
{
if (!Player_eggs_dropped)
{
#ifdef NETWORK
if (Game_mode & GM_NETWORK)
multi_powcap_cap_objects();
#endif
drop_player_eggs(ConsoleObject);
Player_eggs_dropped = 1;
#ifdef NETWORK
if (Game_mode & GM_MULTI)
{
multi_send_player_explode(MULTI_PLAYER_EXPLODE);
}
#endif
}
DoPlayerDead(); //kill_player();
}
}
else
time_dead = 0;

View file

@ -449,199 +449,6 @@ int do_powerup(object *obj)
}
void pow_count_add(int *pow_level, int id, int count, object *pow) {
switch (id) {
case POW_VULCAN_WEAPON:
if (pow != NULL)
pow_level[POW_VULCAN_AMMO] += pow->ctype.powerup_info.count;
else
pow_level[POW_VULCAN_AMMO] += VULCAN_WEAPON_AMMO_AMOUNT * count;
pow_level[POW_VULCAN_WEAPON] += count;
break;
case POW_VULCAN_AMMO:
pow_level[POW_VULCAN_AMMO] += VULCAN_AMMO_AMOUNT * count;
break;
case POW_MISSILE_4:
case POW_HOMING_AMMO_4:
pow_level[id - 1] += 4 * count;
break;
default:
pow_level[id] += count;
}
}
void pow_count_level(int *pow_level) {
int i;
memset(pow_level, 0, MAX_POWERUP_TYPES * sizeof(pow_level[0]));
for (i = 0; i <= Highest_object_index; i++)
if (!(Objects[i].flags & OF_SHOULD_BE_DEAD))
switch (Objects[i].type) {
case OBJ_POWERUP:
pow_count_add(pow_level, Objects[i].id, 1, &Objects[i]);
break;
#if 0 // now not added until released by robot
case OBJ_ROBOT:
if (Objects[i].contains_type == OBJ_POWERUP)
pow_count_add(pow_level, Objects[i].contains_id, Objects[i].contains_count, NULL);
break;
#endif
}
}
void count_powerup_start_level() {
int player_pows[MAX_POWERUP_TYPES];
pow_count_level(powerup_start_level);
player_to_pow_count(&Players[Player_num], player_pows);
pow_add_level_pow_count(player_pows);
}
#ifndef NDEBUG
void dump_pow_count(char *title, int *pow_count);
#endif
// add a random created powerup to the level count
void pow_add_random(object *obj) {
if (obj->contains_count > 0 && obj->contains_type == OBJ_POWERUP)
pow_count_add(powerup_start_level, obj->contains_id, obj->contains_count, NULL);
#ifndef NDEBUG
#ifdef USE_IPX
if (!(Game_mode & GM_NETWORK) ||
Netgame.protocol.ipx.protocol_version != MULTI_PROTO_D1X_VER)
return;
#endif
dump_pow_count("pow_add_random: now start level", powerup_start_level);
#endif
}
void pow_add_level_pow_count(int *pow_count) {
int i;
for (i = 0; i < MAX_POWERUP_TYPES; i++)
powerup_start_level[i] += pow_count[i];
#ifndef NDEBUG
#ifdef USE_IPX
if (!(Game_mode & GM_NETWORK) ||
Netgame.protocol.ipx.protocol_version != MULTI_PROTO_D1X_VER)
return;
#endif
dump_pow_count("pow_add_level_pow_count: pow_count", pow_count);
dump_pow_count("pow_add_level_pow_count: now start level", powerup_start_level);
#endif
}
#if 0 // clipping version
// fill pow_count with items that would be dropped if player dies
void player_to_pow_count(player *player, int *pow_count)
{
memset(pow_count, 0, sizeof(int) * MAX_POWERUP_TYPES);
pow_count[POW_LASER] = player->laser_level;
pow_count[POW_QUAD_FIRE] = (player->flags & PLAYER_FLAGS_QUAD_LASERS) != 0;
pow_count[POW_CLOAK] = (player->flags & PLAYER_FLAGS_CLOAKED) != 0;
pow_count[POW_VULCAN_WEAPON] = (player->primary_weapon_flags & HAS_VULCAN_FLAG) != 0;
pow_count[POW_SPREADFIRE_WEAPON] = (player->primary_weapon_flags & HAS_SPREADFIRE_FLAG) != 0;
pow_count[POW_PLASMA_WEAPON] = (player->primary_weapon_flags & HAS_PLASMA_FLAG) != 0;
pow_count[POW_FUSION_WEAPON] = (player->primary_weapon_flags & HAS_FUSION_FLAG) != 0;
pow_count[POW_MISSILE_1] = MIN(player->secondary_ammo[CONCUSSION_INDEX], 4);
pow_count[POW_HOMING_AMMO_1] = MIN(player->secondary_ammo[HOMING_INDEX], 6);
pow_count[POW_PROXIMITY_WEAPON] = MIN((player->secondary_ammo[PROXIMITY_INDEX]+2)/4, 3);
pow_count[POW_SMARTBOMB_WEAPON] = MIN(player->secondary_ammo[SMART_INDEX], 3);
pow_count[POW_MEGA_WEAPON] = MIN(player->secondary_ammo[MEGA_INDEX], 3);
pow_count[POW_VULCAN_AMMO] = MIN(player->primary_ammo[VULCAN_INDEX], 200);
pow_count[POW_INVULNERABILITY] = (player->flags & PLAYER_FLAGS_INVULNERABLE) != 0;
// Always drop a shield and energy powerup in multiplayer
if (Game_mode & GM_MULTI) {
pow_count[POW_SHIELD_BOOST] = 1;
pow_count[POW_ENERGY] = 1;
}
}
#else
// fill pow_count with items that player currently has
void player_to_pow_count(player *player, int *pow_count)
{
memset(pow_count, 0, sizeof(int) * MAX_POWERUP_TYPES);
pow_count[POW_LASER] = player->laser_level;
pow_count[POW_QUAD_FIRE] = (player->flags & PLAYER_FLAGS_QUAD_LASERS) != 0;
pow_count[POW_CLOAK] = (player->flags & PLAYER_FLAGS_CLOAKED) != 0;
pow_count[POW_VULCAN_WEAPON] = (player->primary_weapon_flags & HAS_VULCAN_FLAG) != 0;
pow_count[POW_SPREADFIRE_WEAPON] = (player->primary_weapon_flags & HAS_SPREADFIRE_FLAG) != 0;
pow_count[POW_PLASMA_WEAPON] = (player->primary_weapon_flags & HAS_PLASMA_FLAG) != 0;
pow_count[POW_FUSION_WEAPON] = (player->primary_weapon_flags & HAS_FUSION_FLAG) != 0;
pow_count[POW_MISSILE_1] = player->secondary_ammo[CONCUSSION_INDEX];
pow_count[POW_HOMING_AMMO_1] = player->secondary_ammo[HOMING_INDEX];
pow_count[POW_PROXIMITY_WEAPON] = (player->secondary_ammo[PROXIMITY_INDEX]+2)/4;
pow_count[POW_SMARTBOMB_WEAPON] = player->secondary_ammo[SMART_INDEX];
pow_count[POW_MEGA_WEAPON] = player->secondary_ammo[MEGA_INDEX];
pow_count[POW_VULCAN_AMMO] = player->primary_ammo[VULCAN_INDEX];
pow_count[POW_INVULNERABILITY] = (player->flags & PLAYER_FLAGS_INVULNERABLE) != 0;
// Always drop a shield and energy powerup in multiplayer
if (Game_mode & GM_MULTI) {
pow_count[POW_SHIELD_BOOST] = 1;
pow_count[POW_ENERGY] = 1;
}
}
#endif
// This must be in a special order to keep the
// Net_create_objnums[] order compatible
int player_drop_powerups[] = { POW_LASER, POW_QUAD_FIRE, POW_CLOAK,
POW_VULCAN_WEAPON, POW_SPREADFIRE_WEAPON, POW_PLASMA_WEAPON,
POW_FUSION_WEAPON, POW_PROXIMITY_WEAPON, POW_SMARTBOMB_WEAPON,
POW_MEGA_WEAPON, POW_HOMING_AMMO_1, POW_VULCAN_AMMO,
POW_MISSILE_1, POW_SHIELD_BOOST, POW_ENERGY,
POW_INVULNERABILITY };
// reduce player drop powerups
void clip_player_pow_count(int *pow_count)
{
int i;
/*laser,quad,cloak,vulc,spread,plasma,fusion,*/
/*prox,smart,mega,hom,vula,con,sh,en,invul*/
static int pow_max[NUM_PLAYER_DROP_POWERUPS] =
{ 3,1,1,1,1,1,1,3,3,3,6,VULCAN_AMMO_MAX,4,1,1,0 };
for (i = 0; i < NUM_PLAYER_DROP_POWERUPS; i++)
if (pow_count[player_drop_powerups[i]] > pow_max[i])
pow_count[player_drop_powerups[i]] = pow_max[i];
}
// may this powerup be added to the level?
// returns number of powerups left if true, -1 if unknown, otherwise 0.
int may_create_powerup(int powerup)
{
#ifdef NETWORK
int pow_count[MAX_POWERUP_TYPES];
if (!(Game_mode & GM_NETWORK)
#ifdef USE_IPX
|| Netgame.protocol.ipx.protocol_version != MULTI_PROTO_D1X_VER
#endif
)
return -1; // say unknown if not in D1X network game
pow_count_level(pow_count);
#ifndef NDEBUG
dump_pow_count("may_create_powerup: now in level:", pow_count);
#endif
// if(powerup==POW_SHIELD_BOOST) return 1;
return max(powerup_start_level[powerup] - pow_count[powerup], 0);
#endif
return -1;
}
#ifndef NDEBUG
void dump_pow_count(char *title, int *pow_count) {
int i, j = 0;
for (i = 0; i < MAX_POWERUP_TYPES; i++) {
if (pow_count[i]) {
j++;
}
}
}
#endif
/*
* reads n powerup_type_info structs from a CFILE
*/

View file

@ -117,26 +117,6 @@ extern void do_megawow_powerup(int quantity);
extern void powerup_basic(int redadd, int greenadd, int blueadd, int score, char *format, ...);
extern void count_powerup_start_level();
extern int powerup_start_level[MAX_POWERUP_TYPES];
extern void pow_count_level();
extern void pow_add_random();
// add pow_count to powerup_start_level
extern void pow_add_level_pow_count(int *pow_count);
// fill pow_count with items that would be dropped if player dies
extern void player_to_pow_count(player *player, int *pow_count);
#define NUM_PLAYER_DROP_POWERUPS 16
extern int player_drop_powerups[NUM_PLAYER_DROP_POWERUPS];
// reduce player drop powerups
extern void clip_player_pow_count(int *pow_count);
// may this powerup be added to the level?
// returns number of powerups left if true, otherwise 0.
extern int may_create_powerup(int powerup);

View file

@ -33,6 +33,10 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
// Convert primary weapons to indices in Weapon_info array.
ubyte Primary_weapon_to_weapon_info[MAX_PRIMARY_WEAPONS] = {0, 11, 12, 13, 14};
ubyte Secondary_weapon_to_weapon_info[MAX_SECONDARY_WEAPONS] = {8, 15, 16, 17, 18};
//for each primary weapon, what kind of powerup gives weapon
ubyte Primary_weapon_to_powerup[MAX_PRIMARY_WEAPONS] = {POW_LASER,POW_VULCAN_WEAPON,POW_SPREADFIRE_WEAPON,POW_PLASMA_WEAPON,POW_FUSION_WEAPON};
//for each Secondary weapon, what kind of powerup gives weapon
ubyte Secondary_weapon_to_powerup[MAX_SECONDARY_WEAPONS] = {POW_MISSILE_1,POW_HOMING_AMMO_1,POW_PROXIMITY_WEAPON,POW_SMARTBOMB_WEAPON,POW_MEGA_WEAPON};
int Primary_ammo_max[MAX_PRIMARY_WEAPONS] = {0, VULCAN_AMMO_MAX, 0, 0, 0};
ubyte Secondary_ammo_max[MAX_SECONDARY_WEAPONS] = {20, 10, 10, 5, 5};
weapon_info Weapon_info[MAX_WEAPON_TYPES];

View file

@ -90,6 +90,9 @@ typedef struct weapon_info {
#define MAX_PRIMARY_WEAPONS 5
#define MAX_SECONDARY_WEAPONS 5
//given a weapon index, return the flag value
#define HAS_FLAG(index) (1<<(index))
// Weapon flags, if player->weapon_flags & WEAPON_FLAG is set, then the player has this weapon
#define HAS_LASER_FLAG 0x001
#define HAS_VULCAN_FLAG 0x002
@ -130,6 +133,10 @@ extern sbyte Primary_weapon, Secondary_weapon;
extern ubyte Primary_weapon_to_weapon_info[MAX_PRIMARY_WEAPONS];
extern ubyte Secondary_weapon_to_weapon_info[MAX_SECONDARY_WEAPONS];
//for each primary weapon, what kind of powerup gives weapon
extern ubyte Primary_weapon_to_powerup[MAX_SECONDARY_WEAPONS];
//for each Secondary weapon, what kind of powerup gives weapon
extern ubyte Secondary_weapon_to_powerup[MAX_SECONDARY_WEAPONS];
extern void auto_select_weapon(int weapon_type); //parm is primary or secondary
extern void select_weapon(int weapon_num, int secondary_flag, int print_message,int wait_for_rearm);