void SV_UpdateEffects(sizebuf_t *sb) { int index; for(index=0;index<MAX_EFFECTS;index++) if (sv.Effects[index].type) SV_SendEffect(sb,index); }
void SV_UpdateEffects (sizebuf_t *sb) { int idx; for (idx = 0 ; idx < MAX_EFFECTS ; idx++) { if (sv.Effects[idx].type) SV_SendEffect(sb, idx); } }
// All changes need to be in SV_SendEffect(), SV_ParseEffect(), // SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect() void SV_ParseEffect (sizebuf_t *sb) { int idx; byte effect; effect = G_FLOAT(OFS_PARM0); for (idx = 0 ; idx < MAX_EFFECTS ; idx++) { if (!sv.Effects[idx].type || (sv.Effects[idx].expire_time && sv.Effects[idx].expire_time <= sv.time)) break; } if (idx >= MAX_EFFECTS) { PR_RunError ("MAX_EFFECTS reached"); return; } // Con_Printf("Effect #%d\n", idx); memset(&sv.Effects[idx], 0, sizeof(struct EffectT)); sv.Effects[idx].type = effect; G_FLOAT(OFS_RETURN) = idx; switch (effect) { case CE_RAIN: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Rain.min_org); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Rain.max_org); VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Rain.e_size); VectorCopy(G_VECTOR(OFS_PARM4), sv.Effects[idx].ef.Rain.dir); sv.Effects[idx].ef.Rain.color = G_FLOAT(OFS_PARM5); sv.Effects[idx].ef.Rain.count = G_FLOAT(OFS_PARM6); sv.Effects[idx].ef.Rain.wait = G_FLOAT(OFS_PARM7); sv.Effects[idx].ef.Rain.next_time = 0; break; case CE_SNOW: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Rain.min_org); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Rain.max_org); sv.Effects[idx].ef.Rain.flags = G_FLOAT(OFS_PARM3); VectorCopy(G_VECTOR(OFS_PARM4), sv.Effects[idx].ef.Rain.dir); sv.Effects[idx].ef.Rain.count = G_FLOAT(OFS_PARM5); //sv.Effects[idx].Rain.veer = G_FLOAT(OFS_PARM6); //sv.Effects[idx].Rain.wait = 0.10; sv.Effects[idx].ef.Rain.next_time = 0; break; case CE_FOUNTAIN: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Fountain.pos); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Fountain.angle); VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Fountain.movedir); sv.Effects[idx].ef.Fountain.color = G_FLOAT(OFS_PARM4); sv.Effects[idx].ef.Fountain.cnt = G_FLOAT(OFS_PARM5); break; case CE_QUAKE: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Quake.origin); sv.Effects[idx].ef.Quake.radius = G_FLOAT(OFS_PARM2); break; case CE_WHITE_SMOKE: case CE_GREEN_SMOKE: case CE_GREY_SMOKE: case CE_RED_SMOKE: case CE_SLOW_WHITE_SMOKE: case CE_TELESMK1: case CE_TELESMK2: case CE_GHOST: case CE_REDCLOUD: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Smoke.origin); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Smoke.velocity); sv.Effects[idx].ef.Smoke.framelength = G_FLOAT(OFS_PARM3); sv.Effects[idx].ef.Smoke.frame = 0; sv.Effects[idx].expire_time = sv.time + 1; break; case CE_ACID_MUZZFL: case CE_FLAMESTREAM: case CE_FLAMEWALL: case CE_FLAMEWALL2: case CE_ONFIRE: /* mission pack */ VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Smoke.origin); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Smoke.velocity); sv.Effects[idx].ef.Smoke.framelength = 0.05; sv.Effects[idx].ef.Smoke.frame = G_FLOAT(OFS_PARM3); sv.Effects[idx].expire_time = sv.time + 1; break; case CE_SM_WHITE_FLASH: case CE_YELLOWRED_FLASH: case CE_BLUESPARK: case CE_YELLOWSPARK: case CE_SM_CIRCLE_EXP: case CE_BG_CIRCLE_EXP: case CE_SM_EXPLOSION: case CE_LG_EXPLOSION: case CE_FLOOR_EXPLOSION: case CE_FLOOR_EXPLOSION3: case CE_BLUE_EXPLOSION: case CE_REDSPARK: case CE_GREENSPARK: case CE_ICEHIT: case CE_MEDUSA_HIT: case CE_MEZZO_REFLECT: case CE_FLOOR_EXPLOSION2: case CE_XBOW_EXPLOSION: case CE_NEW_EXPLOSION: case CE_MAGIC_MISSILE_EXPLOSION: case CE_BONE_EXPLOSION: case CE_BLDRN_EXPL: case CE_ACID_HIT: case CE_ACID_SPLAT: case CE_ACID_EXPL: case CE_LBALL_EXPL: case CE_FIREWALL_SMALL: case CE_FIREWALL_MEDIUM: case CE_FIREWALL_LARGE: case CE_FBOOM: case CE_BOMB: case CE_BRN_BOUNCE: case CE_LSHOCK: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Smoke.origin); sv.Effects[idx].expire_time = sv.time + 1; break; case CE_WHITE_FLASH: case CE_BLUE_FLASH: case CE_SM_BLUE_FLASH: case CE_RED_FLASH: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Flash.origin); sv.Effects[idx].expire_time = sv.time + 1; break; case CE_RIDER_DEATH: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.RD.origin); break; case CE_GRAVITYWELL: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.RD.origin); sv.Effects[idx].ef.RD.color = G_FLOAT(OFS_PARM2); sv.Effects[idx].ef.RD.lifetime = G_FLOAT(OFS_PARM3); break; case CE_TELEPORTERPUFFS: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Teleporter.origin); sv.Effects[idx].expire_time = sv.time + 1; break; case CE_TELEPORTERBODY: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Teleporter.origin); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Teleporter.velocity[0]); sv.Effects[idx].ef.Teleporter.skinnum = G_FLOAT(OFS_PARM3); sv.Effects[idx].expire_time = sv.time + 1; break; case CE_BONESHARD: case CE_BONESHRAPNEL: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Missile.origin); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Missile.velocity); VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Missile.angle); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[idx].ef.Missile.avelocity); sv.Effects[idx].expire_time = sv.time + 10; break; case CE_CHUNK: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[idx].ef.Chunk.origin); sv.Effects[idx].ef.Chunk.type = G_FLOAT(OFS_PARM2); VectorCopy(G_VECTOR(OFS_PARM3), sv.Effects[idx].ef.Chunk.srcVel); sv.Effects[idx].ef.Chunk.numChunks = G_FLOAT(OFS_PARM4); sv.Effects[idx].expire_time = sv.time + 3; break; default: PR_RunError ("%s: bad type", __thisfunc__); } SV_SendEffect(sb, idx); }
// All changes need to be in SV_SendEffect(), SV_ParseEffect(), // SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect() void SV_ParseEffect(sizebuf_t *sb) { int index; byte effect; effect = G_FLOAT(OFS_PARM0); for(index=0;index<MAX_EFFECTS;index++) if (!sv.Effects[index].type || (sv.Effects[index].expire_time && sv.Effects[index].expire_time <= sv.time)) break; if (index >= MAX_EFFECTS) { PR_RunError ("MAX_EFFECTS reached"); return; } // Con_Printf("Effect #%d\n",index); memset(&sv.Effects[index],0,sizeof(struct EffectT)); sv.Effects[index].type = effect; G_FLOAT(OFS_RETURN) = index; switch(effect) { case CE_RAIN: VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Rain.min_org); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Rain.max_org); VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Rain.e_size); VectorCopy(G_VECTOR(OFS_PARM4),sv.Effects[index].Rain.dir); sv.Effects[index].Rain.color = G_FLOAT(OFS_PARM5); sv.Effects[index].Rain.count = G_FLOAT(OFS_PARM6); sv.Effects[index].Rain.wait = G_FLOAT(OFS_PARM7); sv.Effects[index].Rain.next_time = 0; break; case CE_FOUNTAIN: VectorCopy(G_VECTOR(OFS_PARM1),sv.Effects[index].Fountain.pos); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Fountain.angle); VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Fountain.movedir); sv.Effects[index].Fountain.color = G_FLOAT(OFS_PARM4); sv.Effects[index].Fountain.cnt = G_FLOAT(OFS_PARM5); break; case CE_QUAKE: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Quake.origin); sv.Effects[index].Quake.radius = G_FLOAT(OFS_PARM2); break; case CE_WHITE_SMOKE: case CE_GREEN_SMOKE: case CE_GREY_SMOKE: case CE_RED_SMOKE: case CE_SLOW_WHITE_SMOKE: case CE_TELESMK1: case CE_TELESMK2: case CE_GHOST: case CE_REDCLOUD: case CE_RIPPLE: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Smoke.velocity); sv.Effects[index].Smoke.framelength = G_FLOAT(OFS_PARM3); sv.Effects[index].expire_time = sv.time + 1; break; case CE_ACID_MUZZFL: case CE_FLAMESTREAM: case CE_FLAMEWALL: case CE_FLAMEWALL2: case CE_ONFIRE: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Smoke.velocity); sv.Effects[index].Smoke.framelength = 0.05; sv.Effects[index].Smoke.frame = G_FLOAT(OFS_PARM3); sv.Effects[index].expire_time = sv.time + 1; break; case CE_SM_WHITE_FLASH: case CE_YELLOWRED_FLASH: case CE_BLUESPARK: case CE_YELLOWSPARK: case CE_SM_CIRCLE_EXP: case CE_BG_CIRCLE_EXP: case CE_SM_EXPLOSION: case CE_SM_EXPLOSION2: case CE_BG_EXPLOSION: case CE_FLOOR_EXPLOSION: case CE_BLUE_EXPLOSION: case CE_REDSPARK: case CE_GREENSPARK: case CE_ICEHIT: case CE_MEDUSA_HIT: case CE_MEZZO_REFLECT: case CE_FLOOR_EXPLOSION2: case CE_XBOW_EXPLOSION: case CE_NEW_EXPLOSION: case CE_MAGIC_MISSILE_EXPLOSION: case CE_BONE_EXPLOSION: case CE_BLDRN_EXPL: case CE_ACID_HIT: case CE_ACID_SPLAT: case CE_ACID_EXPL: case CE_LBALL_EXPL: case CE_FIREWALL_SMALL: case CE_FIREWALL_MEDIUM: case CE_FIREWALL_LARGE: case CE_FBOOM: case CE_BOMB: case CE_BRN_BOUNCE: case CE_LSHOCK: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Smoke.origin); sv.Effects[index].expire_time = sv.time + 1; break; case CE_WHITE_FLASH: case CE_BLUE_FLASH: case CE_SM_BLUE_FLASH: case CE_HWSPLITFLASH: case CE_RED_FLASH: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Flash.origin); sv.Effects[index].expire_time = sv.time + 1; break; case CE_RIDER_DEATH: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].RD.origin); break; case CE_TELEPORTERPUFFS: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Teleporter.origin); sv.Effects[index].expire_time = sv.time + 1; break; case CE_TELEPORTERBODY: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Teleporter.origin); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Teleporter.velocity[0]); sv.Effects[index].Teleporter.skinnum = G_FLOAT(OFS_PARM3); sv.Effects[index].expire_time = sv.time + 1; break; case CE_BONESHRAPNEL: case CE_HWBONEBALL: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Missile.origin); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.velocity); VectorCopy(G_VECTOR(OFS_PARM3),sv.Effects[index].Missile.angle); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.avelocity); sv.Effects[index].expire_time = sv.time + 10; break; case CE_BONESHARD: case CE_HWRAVENSTAFF: case CE_HWMISSILESTAR: case CE_HWEIDOLONSTAR: case CE_HWRAVENPOWER: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Missile.origin); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.velocity); sv.Effects[index].expire_time = sv.time + 10; break; case CE_DEATHBUBBLES: VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Bubble.offset); sv.Effects[index].Bubble.owner = G_EDICTNUM(OFS_PARM1); sv.Effects[index].Bubble.count = G_FLOAT(OFS_PARM3); sv.Effects[index].expire_time = sv.time + 30; break; case CE_HWDRILLA: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Missile.origin); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Missile.angle); sv.Effects[index].Missile.speed = G_FLOAT(OFS_PARM3); sv.Effects[index].expire_time = sv.time + 10; break; case CE_TRIPMINESTILL: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Chain.origin); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Chain.velocity); sv.Effects[index].expire_time = sv.time + 70; break; case CE_TRIPMINE: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Chain.origin); VectorCopy(G_VECTOR(OFS_PARM2),sv.Effects[index].Chain.velocity); sv.Effects[index].expire_time = sv.time + 10; break; case CE_SCARABCHAIN: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Chain.origin); sv.Effects[index].Chain.owner = G_EDICTNUM(OFS_PARM2); sv.Effects[index].Chain.material = G_INT(OFS_PARM3); sv.Effects[index].Chain.tag = G_INT(OFS_PARM4); sv.Effects[index].Chain.state = 0; sv.Effects[index].expire_time = sv.time + 15; break; case CE_HWSHEEPINATOR: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[0]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[1]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[2]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[3]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[4]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[5]); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Xbow.angle); sv.Effects[index].Xbow.bolts = 5; sv.Effects[index].Xbow.activebolts = 31; sv.Effects[index].Xbow.randseed = 0; sv.Effects[index].Xbow.turnedbolts = 0; sv.Effects[index].expire_time = sv.time + 7; break; case CE_HWXBOWSHOOT: VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[0]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[1]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[2]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[3]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[4]); VectorCopy(G_VECTOR(OFS_PARM1), sv.Effects[index].Xbow.origin[5]); VectorCopy(G_VECTOR(OFS_PARM2), sv.Effects[index].Xbow.angle); sv.Effects[index].Xbow.bolts = G_FLOAT(OFS_PARM3); sv.Effects[index].Xbow.randseed = G_FLOAT(OFS_PARM4); sv.Effects[index].Xbow.turnedbolts = 0; if (sv.Effects[index].Xbow.bolts == 3) { sv.Effects[index].Xbow.activebolts = 7; } else { sv.Effects[index].Xbow.activebolts = 31; } sv.Effects[index].expire_time = sv.time + 15; break; default: // Sys_Error ("SV_ParseEffect: bad type"); PR_RunError ("SV_SendEffect: bad type"); } SV_SendEffect(sb,index); }
/* =================== SV_ExecuteClientMessage The current net_message is parsed for the given client =================== */ void SV_ExecuteClientMessage (client_t *cl) { int c; const char *s; usercmd_t oldest, oldcmd, newcmd; client_frame_t *frame; vec3_t o; // calc ping time frame = &cl->frames[cl->netchan.incoming_acknowledged & UPDATE_MASK]; frame->ping_time = realtime - frame->senttime; // make sure the reply sequence number matches the incoming // sequence number if (cl->netchan.incoming_sequence >= cl->netchan.outgoing_sequence) cl->netchan.outgoing_sequence = cl->netchan.incoming_sequence; else cl->send_message = false; // don't reply, sequences have slipped // save time for ping calculations cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].senttime = realtime; cl->frames[cl->netchan.outgoing_sequence & UPDATE_MASK].ping_time = -1; host_client = cl; sv_player = host_client->edict; // mark time so clients will know how much to predict // other players cl->localtime = sv.time; cl->delta_sequence = -1; // no delta unless requested while (1) { if (msg_badread) { Con_Printf ("%s: badread\n", __thisfunc__); SV_DropClient (cl); return; } c = MSG_ReadByte (); if (c == -1) break; switch (c) { default: Con_Printf ("%s: unknown command char\n", __thisfunc__); SV_DropClient (cl); return; case clc_nop: break; case clc_delta: cl->delta_sequence = MSG_ReadByte (); break; case clc_move: MSG_ReadUsercmd (&oldest, false); MSG_ReadUsercmd (&oldcmd, false); MSG_ReadUsercmd (&newcmd, true); if ( cl->state != cs_spawned ) break; SV_PreRunCmd(); if (net_drop < 20) { while (net_drop > 2) { SV_RunCmd (&cl->lastcmd); net_drop--; } if (net_drop > 1) SV_RunCmd (&oldest); if (net_drop > 0) SV_RunCmd (&oldcmd); } SV_RunCmd (&newcmd); SV_PostRunCmd(); cl->lastcmd = newcmd; cl->lastcmd.buttons = 0; // avoid multiple fires on lag break; case clc_stringcmd: s = MSG_ReadString (); SV_ExecuteUserCommand (s); break; case clc_tmove: o[0] = MSG_ReadCoord(); o[1] = MSG_ReadCoord(); o[2] = MSG_ReadCoord(); // only allowed by spectators if (host_client->spectator) { VectorCopy(o, sv_player->v.origin); SV_LinkEdict(sv_player, false); } break; case clc_inv_select: cl->edict->v.inventory = MSG_ReadByte(); break; case clc_get_effect: c = MSG_ReadByte(); if (sv.Effects[c].type) { Con_Printf("Getting effect %d\n",(int)c); SV_SendEffect(&host_client->netchan.message, c); } break; } } }