void QCBUILTIN PF_cl_GetBindMap (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { int bm[2]; Key_GetBindMap(bm); G_VECTOR(OFS_RETURN)[0] = bm[0]; G_VECTOR(OFS_RETURN)[1] = bm[1]; G_VECTOR(OFS_RETURN)[2] = 0; }
void SV_ParseMultiEffect (sizebuf_t *sb) { int idx, count; byte effect; vec3_t orig, vel; MultiEffectIdCount = 0; effect = G_FLOAT(OFS_PARM0); switch (effect) { case CE_HWRAVENPOWER: // need to set aside 3 effect ids MSG_WriteByte (sb, svc_multieffect); MSG_WriteByte (sb, effect); VectorCopy(G_VECTOR(OFS_PARM1), orig); MSG_WriteCoord(sb, orig[0]); MSG_WriteCoord(sb, orig[1]); MSG_WriteCoord(sb, orig[2]); VectorCopy(G_VECTOR(OFS_PARM2), vel); MSG_WriteCoord(sb, vel[0]); MSG_WriteCoord(sb, vel[1]); MSG_WriteCoord(sb, vel[2]); for (count = 0 ; count < 3 ; count++) { 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; } MSG_WriteByte(sb, idx); sv.Effects[idx].type = CE_HWRAVENPOWER; VectorCopy(orig, sv.Effects[idx].ef.Missile.origin); VectorCopy(vel, sv.Effects[idx].ef.Missile.velocity); sv.Effects[idx].expire_time = sv.time + 10; MultiEffectIds[count] = idx; } break; default: PR_RunError ("%s: bad type", __thisfunc__); } }
// #493 vector(string name) gecko_get_texture_extent void QCBUILTIN PF_cs_media_get_texture_extent (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { const char *shader = PR_GetStringOfs(prinst, OFS_PARM0); float *ret = G_VECTOR(OFS_RETURN); int sx = 0, sy = 0; float aspect = 0; cin_t *cin; cin = R_ShaderFindCinematic(shader); if (cin) Media_Send_GetSize(cin, &sx, &sy, &aspect); ret[0] = sx; ret[1] = sy; ret[2] = aspect; }
//a bit pointless really void QCBUILTIN PF_cl_getresolution (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals) { float mode = G_FLOAT(OFS_PARM0); // qboolean fixedmodes = (prinst->callargc >= 2)?!G_FLOAT(OFS_PARM1):false; //if true, we should return sane-sized modes suitable for a window... or the mod could make up its own, but whatever. float *ret = G_VECTOR(OFS_RETURN); int w, h; w=h=0; if (mode == -1) { int bpp, rate; Sys_GetDesktopParameters(&w, &h, &bpp, &rate); } else M_Vid_GetMode(mode, &w, &h); ret[0] = w; ret[1] = h; ret[2] = (w&&h)?1:0; }
// 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); }
void PR_ExecuteProgram(func_t fnum) { int i; int s; eval_t *a, *b, *c; eval_t *ptr; dstatement_t *st; dfunction_t *f, *newf; int runaway; edict_t *ed; int exitdepth; int startFrame; int endFrame; float val; int case_type=-1; float switch_float; if(!fnum || fnum >= progs->numfunctions) { if(pr_global_struct->self) { ED_Print(PROG_TO_EDICT(pr_global_struct->self)); } Host_Error("PR_ExecuteProgram: NULL function"); } f = &pr_functions[fnum]; runaway = 100000; pr_trace = false; exitdepth = pr_depth; s = EnterFunction(f); #ifdef TIMESNAP_ACTIVE ProgsTimer(); // Init #endif while (1) { s++; // Next statement st = &pr_statements[s]; a = (eval_t *)&pr_globals[(unsigned short)st->a]; b = (eval_t *)&pr_globals[(unsigned short)st->b]; c = (eval_t *)&pr_globals[(unsigned short)st->c]; if(!--runaway) { PR_RunError("runaway loop error"); } #ifndef TIMESNAP_ACTIVE pr_xfunction->profile++; #endif pr_xstatement = s; if(pr_trace) { PrintStatement(st); } switch(st->op) { case OP_ADD_F: c->_float = a->_float + b->_float; break; case OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP_SUB_F: c->_float = a->_float - b->_float; break; case OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP_MUL_F: c->_float = a->_float * b->_float; break; case OP_MUL_V: c->_float = a->vector[0]*b->vector[0] + a->vector[1]*b->vector[1] + a->vector[2]*b->vector[2]; break; case OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP_DIV_F: c->_float = a->_float / b->_float; break; case OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP_GE: c->_float = a->_float >= b->_float; break; case OP_LE: c->_float = a->_float <= b->_float; break; case OP_GT: c->_float = a->_float > b->_float; break; case OP_LT: c->_float = a->_float < b->_float; break; case OP_AND: c->_float = a->_float && b->_float; break; case OP_OR: c->_float = a->_float || b->_float; break; case OP_NOT_F: c->_float = !a->_float; break; case OP_NOT_V: c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; break; case OP_NOT_S: c->_float = !a->string || !pr_strings[a->string]; break; case OP_NOT_FNC: c->_float = !a->function; break; case OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); break; case OP_EQ_F: c->_float = a->_float == b->_float; break; case OP_EQ_V: c->_float = (a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]); break; case OP_EQ_S: c->_float = !strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_EQ_E: c->_float = a->_int == b->_int; break; case OP_EQ_FNC: c->_float = a->function == b->function; break; case OP_NE_F: c->_float = a->_float != b->_float; break; case OP_NE_V: c->_float = (a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2]); break; case OP_NE_S: c->_float = strcmp(pr_strings+a->string,pr_strings+b->string); break; case OP_NE_E: c->_float = a->_int != b->_int; break; case OP_NE_FNC: c->_float = a->function != b->function; break; case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_int = a->_int; break; case OP_STOREP_V: ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->vector[0] = a->vector[0]; ptr->vector[1] = a->vector[1]; ptr->vector[2] = a->vector[2]; break; case OP_MULSTORE_F: // f *= f b->_float *= a->_float; break; case OP_MULSTORE_V: // v *= f b->vector[0] *= a->_float; b->vector[1] *= a->_float; b->vector[2] *= a->_float; break; case OP_MULSTOREP_F: // e.f *= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float *= a->_float); break; case OP_MULSTOREP_V: // e.v *= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->vector[0] = (ptr->vector[0] *= a->_float); c->vector[0] = (ptr->vector[1] *= a->_float); c->vector[0] = (ptr->vector[2] *= a->_float); break; case OP_DIVSTORE_F: // f /= f b->_float /= a->_float; break; case OP_DIVSTOREP_F: // e.f /= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float /= a->_float); break; case OP_ADDSTORE_F: // f += f b->_float += a->_float; break; case OP_ADDSTORE_V: // v += v b->vector[0] += a->vector[0]; b->vector[1] += a->vector[1]; b->vector[2] += a->vector[2]; break; case OP_ADDSTOREP_F: // e.f += f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float += a->_float); break; case OP_ADDSTOREP_V: // e.v += v ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->vector[0] = (ptr->vector[0] += a->vector[0]); c->vector[1] = (ptr->vector[1] += a->vector[1]); c->vector[2] = (ptr->vector[2] += a->vector[2]); break; case OP_SUBSTORE_F: // f -= f b->_float -= a->_float; break; case OP_SUBSTORE_V: // v -= v b->vector[0] -= a->vector[0]; b->vector[1] -= a->vector[1]; b->vector[2] -= a->vector[2]; break; case OP_SUBSTOREP_F: // e.f -= f ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->_float = (ptr->_float -= a->_float); break; case OP_SUBSTOREP_V: // e.v -= v ptr = (eval_t *)((byte *)sv.edicts+b->_int); c->vector[0] = (ptr->vector[0] -= a->vector[0]); c->vector[1] = (ptr->vector[1] -= a->vector[1]); c->vector[2] = (ptr->vector[2] -= a->vector[2]); break; case OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if(ed == (edict_t *)sv.edicts && sv.state == ss_active) { PR_RunError("assignment to world entity"); } c->_int = (byte *)((int *)&ed->v + b->_int)-(byte *)sv.edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif a = (eval_t *)((int *)&ed->v+b->_int); c->_int = a->_int; break; case OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif a = (eval_t *)((int *)&ed->v + b->_int); c->vector[0] = a->vector[0]; c->vector[1] = a->vector[1]; c->vector[2] = a->vector[2]; break; case OP_FETCH_GBL_F: case OP_FETCH_GBL_S: case OP_FETCH_GBL_E: case OP_FETCH_GBL_FNC: i = (int)b->_float; if(i < 0 || i > G_INT((unsigned short)st->a - 1)) { PR_RunError("array index out of bounds: %d", i); } a = (eval_t *)&pr_globals[(unsigned short)st->a + i]; c->_int = a->_int; break; case OP_FETCH_GBL_V: i = (int)b->_float; if(i < 0 || i > G_INT((unsigned short)st->a - 1)) { PR_RunError("array index out of bounds: %d", i); } a = (eval_t *)&pr_globals[(unsigned short)st->a +((int)b->_float)*3]; c->vector[0] = a->vector[0]; c->vector[1] = a->vector[1]; c->vector[2] = a->vector[2]; break; case OP_IFNOT: if(!a->_int) { s += st->b-1; // -1 to offset the s++ } break; case OP_IF: if(a->_int) { s += st->b-1; // -1 to offset the s++ } break; case OP_GOTO: s += st->a-1; // -1 to offset the s++ break; case OP_CALL8: case OP_CALL7: case OP_CALL6: case OP_CALL5: case OP_CALL4: case OP_CALL3: case OP_CALL2: // Copy second arg to shared space VectorCopy(c->vector, G_VECTOR(OFS_PARM1)); case OP_CALL1: // Copy first arg to shared space VectorCopy(b->vector, G_VECTOR(OFS_PARM0)); case OP_CALL0: pr_argc = st->op-OP_CALL0; if(!a->function) { PR_RunError("NULL function"); } newf = &pr_functions[a->function]; if(newf->first_statement < 0) { // Built-in function i = -newf->first_statement; if(i >= pr_numbuiltins) { PR_RunError("Bad builtin call number"); } pr_builtins[i](); break; } // Normal function #ifdef TIMESNAP_ACTIVE pr_xfunction->profile += ProgsTimer(); #endif s = EnterFunction(newf); break; case OP_DONE: case OP_RETURN: pr_globals[OFS_RETURN] = pr_globals[(unsigned short)st->a]; pr_globals[OFS_RETURN+1] = pr_globals[(unsigned short)st->a+1]; pr_globals[OFS_RETURN+2] = pr_globals[(unsigned short)st->a+2]; #ifdef TIMESNAP_ACTIVE pr_xfunction->profile += ProgsTimer(); #endif s = LeaveFunction(); if(pr_depth == exitdepth) { // Done return; } break; case OP_STATE: ed = PROG_TO_EDICT(pr_global_struct->self); /* Id 1.07 changes #ifdef FPS_20 ed->v.nextthink = pr_global_struct->time + 0.05; #else ed->v.nextthink = pr_global_struct->time + 0.1; #endif */ ed->v.nextthink = pr_global_struct->time+HX_FRAME_TIME; if(a->_float != ed->v.frame) { ed->v.frame = a->_float; } ed->v.think = b->function; break; case OP_CSTATE: // Cycle state ed = PROG_TO_EDICT(pr_global_struct->self); ed->v.nextthink = pr_global_struct->time+HX_FRAME_TIME; ed->v.think = pr_xfunction-pr_functions; pr_global_struct->cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if(startFrame <= endFrame) { // Increment if(ed->v.frame < startFrame || ed->v.frame > endFrame) { ed->v.frame = startFrame; break; } ed->v.frame++; if(ed->v.frame > endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.frame = startFrame; } break; } // Decrement if(ed->v.frame > startFrame || ed->v.frame < endFrame) { ed->v.frame = startFrame; break; } ed->v.frame--; if(ed->v.frame < endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.frame = startFrame; } break; case OP_CWSTATE: // Cycle weapon state ed = PROG_TO_EDICT(pr_global_struct->self); ed->v.nextthink = pr_global_struct->time+HX_FRAME_TIME; ed->v.think = pr_xfunction-pr_functions; pr_global_struct->cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if(startFrame <= endFrame) { // Increment if(ed->v.weaponframe < startFrame || ed->v.weaponframe > endFrame) { ed->v.weaponframe = startFrame; break; } ed->v.weaponframe++; if(ed->v.weaponframe > endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.weaponframe = startFrame; } break; } // Decrement if(ed->v.weaponframe > startFrame || ed->v.weaponframe < endFrame) { ed->v.weaponframe = startFrame; break; } ed->v.weaponframe--; if(ed->v.weaponframe < endFrame) { pr_global_struct->cycle_wrapped = true; ed->v.weaponframe = startFrame; } break; case OP_THINKTIME: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if(ed == (edict_t *)sv.edicts && sv.state == ss_active) { PR_RunError("assignment to world entity"); } ed->v.nextthink = pr_global_struct->time+b->_float; break; case OP_BITSET: // f (+) f b->_float = (int)b->_float | (int)a->_float; break; case OP_BITSETP: // e.f (+) f ptr = (eval_t *)((byte *)sv.edicts+b->_int); ptr->_float = (int)ptr->_float | (int)a->_float; break; case OP_BITCLR: // f (-) f b->_float = (int)b->_float & ~((int)a->_float); break; case OP_BITCLRP: // e.f (-) f ptr = (eval_t *)((byte *)sv.edicts+b->_int); ptr->_float = (int)ptr->_float & ~((int)a->_float); break; case OP_RAND0: val = rand()*(1.0/RAND_MAX);//(rand()&0x7fff)/((float)0x7fff); G_FLOAT(OFS_RETURN) = val; break; case OP_RAND1: val = rand()*(1.0/RAND_MAX)*a->_float; G_FLOAT(OFS_RETURN) = val; break; case OP_RAND2: if(a->_float < b->_float) { val = a->_float+(rand()*(1.0/RAND_MAX) *(b->_float-a->_float)); } else { val = b->_float+(rand()*(1.0/RAND_MAX) *(a->_float-b->_float)); } G_FLOAT(OFS_RETURN) = val; break; case OP_RANDV0: val = rand()*(1.0/RAND_MAX); G_FLOAT(OFS_RETURN+0) = val; val = rand()*(1.0/RAND_MAX); G_FLOAT(OFS_RETURN+1) = val; val = rand()*(1.0/RAND_MAX); G_FLOAT(OFS_RETURN+2) = val; break; case OP_RANDV1: val = rand()*(1.0/RAND_MAX)*a->vector[0]; G_FLOAT(OFS_RETURN+0) = val; val = rand()*(1.0/RAND_MAX)*a->vector[1]; G_FLOAT(OFS_RETURN+1) = val; val = rand()*(1.0/RAND_MAX)*a->vector[2]; G_FLOAT(OFS_RETURN+2) = val; break; case OP_RANDV2: for(i = 0; i < 3; i++) { if(a->vector[i] < b->vector[i]) { val = a->vector[i]+(rand()*(1.0/RAND_MAX) *(b->vector[i]-a->vector[i])); } else { val = b->vector[i]+(rand()*(1.0/RAND_MAX) *(a->vector[i]-b->vector[i])); } G_FLOAT(OFS_RETURN+i) = val; } break; case OP_SWITCH_F: case_type = SWITCH_F; switch_float = a->_float; s += st->b-1; // -1 to offset the s++ break; case OP_SWITCH_V: PR_RunError("switch v not done yet!"); break; case OP_SWITCH_S: PR_RunError("switch s not done yet!"); break; case OP_SWITCH_E: PR_RunError("switch e not done yet!"); break; case OP_SWITCH_FNC: PR_RunError("switch fnc not done yet!"); break; case OP_CASERANGE: if (case_type!=SWITCH_F) PR_RunError("caserange f****d!"); if((switch_float >= a->_float) && (switch_float <= b->_float)) { s += st->c-1; // -1 to offset the s++ } break; case OP_CASE: switch (case_type) { case SWITCH_F: if(switch_float == a->_float) { s += st->b-1; // -1 to offset the s++ } break; case SWITCH_V: case SWITCH_S: case SWITCH_E: case SWITCH_FNC: PR_RunError("case not done yet!"); break; default: PR_RunError("f****d case!"); } break; default: PR_RunError("Bad opcode %i", st->op); } } }
void PR_ExecuteProgram (func_t fnum) { eval_t *ptr, *a, *b, *c; float *vecptr; dstatement_t *st; dfunction_t *f, *newf; edict_t *ed; int jump_ofs; int exitdepth; int profile, startprofile; /* switch/case support: */ int case_type = -1; float switch_float = 0; if (!fnum || fnum >= progs->numfunctions) { if (*sv_globals.self) { ED_Print(PROG_TO_EDICT(*sv_globals.self)); } Host_Error("%s: NULL function", __thisfunc__); } f = &pr_functions[fnum]; pr_trace = false; exitdepth = pr_depth; st = &pr_statements[EnterFunction(f)]; startprofile = profile = 0; while (1) { st++; /* next statement */ a = OPA; b = OPB; c = OPC; if (++profile > 100000) { pr_xstatement = st - pr_statements; PR_RunError("runaway loop error"); } if (pr_trace) { PrintStatement(st); } switch (st->op) { case OP_ADD_F: c->_float = a->_float + b->_float; break; case OP_ADD_V: c->vector[0] = a->vector[0] + b->vector[0]; c->vector[1] = a->vector[1] + b->vector[1]; c->vector[2] = a->vector[2] + b->vector[2]; break; case OP_SUB_F: c->_float = a->_float - b->_float; break; case OP_SUB_V: c->vector[0] = a->vector[0] - b->vector[0]; c->vector[1] = a->vector[1] - b->vector[1]; c->vector[2] = a->vector[2] - b->vector[2]; break; case OP_MUL_F: c->_float = a->_float * b->_float; break; case OP_MUL_V: c->_float = a->vector[0] * b->vector[0] + a->vector[1] * b->vector[1] + a->vector[2] * b->vector[2]; break; case OP_MUL_FV: c->vector[0] = a->_float * b->vector[0]; c->vector[1] = a->_float * b->vector[1]; c->vector[2] = a->_float * b->vector[2]; break; case OP_MUL_VF: c->vector[0] = b->_float * a->vector[0]; c->vector[1] = b->_float * a->vector[1]; c->vector[2] = b->_float * a->vector[2]; break; case OP_DIV_F: c->_float = a->_float / b->_float; break; case OP_BITAND: c->_float = (int)a->_float & (int)b->_float; break; case OP_BITOR: c->_float = (int)a->_float | (int)b->_float; break; case OP_GE: c->_float = a->_float >= b->_float; break; case OP_LE: c->_float = a->_float <= b->_float; break; case OP_GT: c->_float = a->_float > b->_float; break; case OP_LT: c->_float = a->_float < b->_float; break; case OP_AND: c->_float = a->_float && b->_float; break; case OP_OR: c->_float = a->_float || b->_float; break; case OP_NOT_F: c->_float = !a->_float; break; case OP_NOT_V: c->_float = !a->vector[0] && !a->vector[1] && !a->vector[2]; break; case OP_NOT_S: c->_float = !a->string || !*PR_GetString(a->string); break; case OP_NOT_FNC: c->_float = !a->function; break; case OP_NOT_ENT: c->_float = (PROG_TO_EDICT(a->edict) == sv.edicts); break; case OP_EQ_F: c->_float = a->_float == b->_float; break; case OP_EQ_V: c->_float = (a->vector[0] == b->vector[0]) && (a->vector[1] == b->vector[1]) && (a->vector[2] == b->vector[2]); break; case OP_EQ_S: c->_float = !strcmp(PR_GetString(a->string), PR_GetString(b->string)); break; case OP_EQ_E: c->_float = a->_int == b->_int; break; case OP_EQ_FNC: c->_float = a->function == b->function; break; case OP_NE_F: c->_float = a->_float != b->_float; break; case OP_NE_V: c->_float = (a->vector[0] != b->vector[0]) || (a->vector[1] != b->vector[1]) || (a->vector[2] != b->vector[2]); break; case OP_NE_S: c->_float = strcmp(PR_GetString(a->string), PR_GetString(b->string)); break; case OP_NE_E: c->_float = a->_int != b->_int; break; case OP_NE_FNC: c->_float = a->function != b->function; break; case OP_STORE_F: case OP_STORE_ENT: case OP_STORE_FLD: // integers case OP_STORE_S: case OP_STORE_FNC: // pointers b->_int = a->_int; break; case OP_STORE_V: b->vector[0] = a->vector[0]; b->vector[1] = a->vector[1]; b->vector[2] = a->vector[2]; break; case OP_STOREP_F: case OP_STOREP_ENT: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_int = a->_int; break; case OP_STOREP_V: ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->vector[0] = a->vector[0]; ptr->vector[1] = a->vector[1]; ptr->vector[2] = a->vector[2]; break; case OP_MULSTORE_F: // f *= f b->_float *= a->_float; break; case OP_MULSTORE_V: // v *= f b->vector[0] *= a->_float; b->vector[1] *= a->_float; b->vector[2] *= a->_float; break; case OP_MULSTOREP_F: // e.f *= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float *= a->_float); break; case OP_MULSTOREP_V: // e.v *= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->vector[0] = (ptr->vector[0] *= a->_float); c->vector[0] = (ptr->vector[1] *= a->_float); c->vector[0] = (ptr->vector[2] *= a->_float); break; case OP_DIVSTORE_F: // f /= f b->_float /= a->_float; break; case OP_DIVSTOREP_F: // e.f /= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float /= a->_float); break; case OP_ADDSTORE_F: // f += f b->_float += a->_float; break; case OP_ADDSTORE_V: // v += v b->vector[0] += a->vector[0]; b->vector[1] += a->vector[1]; b->vector[2] += a->vector[2]; break; case OP_ADDSTOREP_F: // e.f += f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float += a->_float); break; case OP_ADDSTOREP_V: // e.v += v ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->vector[0] = (ptr->vector[0] += a->vector[0]); c->vector[1] = (ptr->vector[1] += a->vector[1]); c->vector[2] = (ptr->vector[2] += a->vector[2]); break; case OP_SUBSTORE_F: // f -= f b->_float -= a->_float; break; case OP_SUBSTORE_V: // v -= v b->vector[0] -= a->vector[0]; b->vector[1] -= a->vector[1]; b->vector[2] -= a->vector[2]; break; case OP_SUBSTOREP_F: // e.f -= f ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->_float = (ptr->_float -= a->_float); break; case OP_SUBSTOREP_V: // e.v -= v ptr = (eval_t *)((byte *)sv.edicts + b->_int); c->vector[0] = (ptr->vector[0] -= a->vector[0]); c->vector[1] = (ptr->vector[1] -= a->vector[1]); c->vector[2] = (ptr->vector[2] -= a->vector[2]); break; case OP_ADDRESS: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if (ed == (edict_t *)sv.edicts && sv.state == ss_active) { pr_xstatement = st - pr_statements; PR_RunError("assignment to world entity"); } c->_int = (byte *)((int *)&ed->v + b->_int) - (byte *)sv.edicts; break; case OP_LOAD_F: case OP_LOAD_FLD: case OP_LOAD_ENT: case OP_LOAD_S: case OP_LOAD_FNC: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif ptr = (eval_t *)((int *)&ed->v + b->_int); c->_int = ptr->_int; break; case OP_LOAD_V: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif ptr = (eval_t *)((int *)&ed->v + b->_int); c->vector[0] = ptr->vector[0]; c->vector[1] = ptr->vector[1]; c->vector[2] = ptr->vector[2]; break; case OP_FETCH_GBL_F: case OP_FETCH_GBL_S: case OP_FETCH_GBL_E: case OP_FETCH_GBL_FNC: { int i = (int)b->_float; if (i < 0 || i > G_INT(st->a - 1)) { pr_xstatement = st - pr_statements; PR_RunError("array index out of bounds: %d", i); } ptr = (eval_t *)&pr_globals[st->a + i]; c->_int = ptr->_int; } break; case OP_FETCH_GBL_V: { int i = (int)b->_float; if (i < 0 || i > G_INT(st->a - 1)) { pr_xstatement = st - pr_statements; PR_RunError("array index out of bounds: %d", i); } ptr = (eval_t *)&pr_globals[st->a + (i * 3)]; c->vector[0] = ptr->vector[0]; c->vector[1] = ptr->vector[1]; c->vector[2] = ptr->vector[2]; } break; case OP_IFNOT: if (!a->_int) { /* Pa3PyX: a, b, and c used to be signed shorts for progs v6, * now they are signed ints. The problem is, they were used * as signed sometimes and as unsigned other times - most of * the time they were used as unsigned with an explicit cast * in PR_ExecuteProgram(). When we convert the old progs to * to the new format in PR_ConvertOldStmts(), we zero-extend * them instead of sign-extending them for that reason: if we * sign-extend them, most of the code will not work - we will * have negative array offsets in PR_ExecuteProgram(), among * other things. Note that they are cast to unsigned short * in PR_ConvertOldStmts() prior to assigning them to what is * now int. There are a few instances where these shorts are * used as signed as in the case below where negative offsets * are needed. Since we now have a zero-extended number in a, * b, and c, we must change it back to signed short, so that * when it is added with and assigned to an int, the result * ends up sign-extended and we get a proper negative offset, * if there is one. */ jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case OP_IF: if (a->_int) { jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case OP_GOTO: jump_ofs = st->a; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ break; case OP_CALL8: case OP_CALL7: case OP_CALL6: case OP_CALL5: case OP_CALL4: case OP_CALL3: case OP_CALL2: // Copy second arg to shared space vecptr = G_VECTOR(OFS_PARM1); VectorCopy(c->vector, vecptr); case OP_CALL1: // Copy first arg to shared space vecptr = G_VECTOR(OFS_PARM0); VectorCopy(b->vector, vecptr); case OP_CALL0: pr_xfunction->profile += profile - startprofile; startprofile = profile; pr_xstatement = st - pr_statements; pr_argc = st->op - OP_CALL0; if (!a->function) { PR_RunError("NULL function"); } newf = &pr_functions[a->function]; if (newf->first_statement < 0) { // Built-in function int i = -newf->first_statement; if (i >= pr_numbuiltins) { PR_RunError("Bad builtin call number %d", i); } pr_builtins[i](); break; } // Normal function st = &pr_statements[EnterFunction(newf)]; break; case OP_DONE: case OP_RETURN: { float *retptr = &pr_globals[OFS_RETURN]; float *valptr = &pr_globals[st->a]; pr_xfunction->profile += profile - startprofile; startprofile = profile; pr_xstatement = st - pr_statements; *retptr++ = *valptr++; *retptr++ = *valptr++; *retptr = *valptr; st = &pr_statements[LeaveFunction()]; if (pr_depth == exitdepth) { // Done return; } } break; case OP_STATE: ed = PROG_TO_EDICT(*sv_globals.self); /* Id 1.07 changes #ifdef FPS_20 ed->v.nextthink = *sv_globals.time + 0.05; #else ed->v.nextthink = *sv_globals.time + 0.1; #endif */ ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME; ed->v.frame = a->_float; ed->v.think = b->function; break; case OP_CSTATE: // Cycle state { int startFrame, endFrame; ed = PROG_TO_EDICT(*sv_globals.self); ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME; ed->v.think = pr_xfunction - pr_functions; *sv_globals.cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if (startFrame <= endFrame) { // Increment if (ed->v.frame < startFrame || ed->v.frame > endFrame) { ed->v.frame = startFrame; } else { ed->v.frame++; if (ed->v.frame > endFrame) { *sv_globals.cycle_wrapped = true; ed->v.frame = startFrame; } } } else { // Decrement if (ed->v.frame > startFrame || ed->v.frame < endFrame) { ed->v.frame = startFrame; } else { ed->v.frame--; if (ed->v.frame < endFrame) { *sv_globals.cycle_wrapped = true; ed->v.frame = startFrame; } } } } break; case OP_CWSTATE: // Cycle weapon state { int startFrame, endFrame; ed = PROG_TO_EDICT(*sv_globals.self); ed->v.nextthink = *sv_globals.time + HX_FRAME_TIME; ed->v.think = pr_xfunction - pr_functions; *sv_globals.cycle_wrapped = false; startFrame = (int)a->_float; endFrame = (int)b->_float; if (startFrame <= endFrame) { // Increment if (ed->v.weaponframe < startFrame || ed->v.weaponframe > endFrame) { ed->v.weaponframe = startFrame; } else { ed->v.weaponframe++; if (ed->v.weaponframe > endFrame) { *sv_globals.cycle_wrapped = true; ed->v.weaponframe = startFrame; } } } else { // Decrement if (ed->v.weaponframe > startFrame || ed->v.weaponframe < endFrame) { ed->v.weaponframe = startFrame; } else { ed->v.weaponframe--; if (ed->v.weaponframe < endFrame) { *sv_globals.cycle_wrapped = true; ed->v.weaponframe = startFrame; } } } } break; case OP_THINKTIME: ed = PROG_TO_EDICT(a->edict); #ifdef PARANOID NUM_FOR_EDICT(ed); // Make sure it's in range #endif if (ed == (edict_t *)sv.edicts && sv.state == ss_active) { pr_xstatement = st - pr_statements; PR_RunError("assignment to world entity"); } ed->v.nextthink = *sv_globals.time + b->_float; break; case OP_BITSET: // f (+) f b->_float = (int)b->_float | (int)a->_float; break; case OP_BITSETP: // e.f (+) f ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_float = (int)ptr->_float | (int)a->_float; break; case OP_BITCLR: // f (-) f b->_float = (int)b->_float & ~((int)a->_float); break; case OP_BITCLRP: // e.f (-) f ptr = (eval_t *)((byte *)sv.edicts + b->_int); ptr->_float = (int)ptr->_float & ~((int)a->_float); break; case OP_RAND0: { float val; val = rand() * (1.0 / RAND_MAX); G_FLOAT(OFS_RETURN) = val; } break; case OP_RAND1: { float val; val = rand() * (1.0 / RAND_MAX) * a->_float; G_FLOAT(OFS_RETURN) = val; } break; case OP_RAND2: { float val; if (a->_float < b->_float) { val = a->_float + (rand() * (1.0 / RAND_MAX) * (b->_float - a->_float)); } else { val = b->_float + (rand() * (1.0 / RAND_MAX) * (a->_float - b->_float)); } G_FLOAT(OFS_RETURN) = val; } break; case OP_RANDV0: { float val; float *retptr = &G_FLOAT(OFS_RETURN); val = rand() * (1.0 / RAND_MAX); *retptr++ = val; val = rand() * (1.0 / RAND_MAX); *retptr++ = val; val = rand() * (1.0 / RAND_MAX); *retptr = val; } break; case OP_RANDV1: { float val; float *retptr = &G_FLOAT(OFS_RETURN); val = rand() * (1.0 / RAND_MAX) * a->vector[0]; *retptr++ = val; val = rand() * (1.0 / RAND_MAX) * a->vector[1]; *retptr++ = val; val = rand() * (1.0 / RAND_MAX) * a->vector[2]; *retptr = val; } break; case OP_RANDV2: { float val; int i; float *retptr = &G_FLOAT(OFS_RETURN); for (i = 0; i < 3; i++) { if (a->vector[i] < b->vector[i]) { val = a->vector[i] + (rand() * (1.0 / RAND_MAX) * (b->vector[i] - a->vector[i])); } else { val = b->vector[i] + (rand() * (1.0 / RAND_MAX) * (a->vector[i] - b->vector[i])); } *retptr++ = val; } } break; case OP_SWITCH_F: case_type = SWITCH_F; switch_float = a->_float; jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ break; case OP_SWITCH_V: case OP_SWITCH_S: case OP_SWITCH_E: case OP_SWITCH_FNC: pr_xstatement = st - pr_statements; PR_RunError("%s not done yet!", pr_opnames[st->op]); break; case OP_CASERANGE: if (case_type != SWITCH_F) { pr_xstatement = st - pr_statements; PR_RunError("caserange f****d!"); } if ((switch_float >= a->_float) && (switch_float <= b->_float)) { jump_ofs = st->c; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case OP_CASE: switch (case_type) { case SWITCH_F: if (switch_float == a->_float) { jump_ofs = st->b; if (is_progs_v6) jump_ofs = (signed short)jump_ofs; st += jump_ofs - 1; /* -1 to offset the st++ */ } break; case SWITCH_V: case SWITCH_S: case SWITCH_E: case SWITCH_FNC: pr_xstatement = st - pr_statements; PR_RunError("OP_CASE for %s not done yet!", pr_opnames[case_type + OP_SWITCH_F - SWITCH_F]); break; default: pr_xstatement = st - pr_statements; PR_RunError("f****d case!"); } break; default: pr_xstatement = st - pr_statements; PR_RunError("Bad opcode %i", st->op); } } /* end of while(1) loop */ }