// All changes need to be in SV_SendEffect(), SV_ParseEffect(), // SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect() void SV_LoadEffects (FILE *FH) { int idx, Total, count; int c; unsigned int u; Total = idx = -1; /* Since the map is freshly loaded, clear out any effects as a result of the loading */ SV_ClearEffects(); fscanf(FH, "Effects: %d\n", &Total); if (Total < 0 || Total > MAX_EFFECTS) Host_Error ("%s: bad numeffects", __thisfunc__); for (count = 0 ; count < Total ; idx = -1, count++) { fscanf(FH, "Effect: %d ", &idx); if (idx < 0 || idx >= MAX_EFFECTS) Host_Error ("%s: bad index", __thisfunc__); fscanf(FH, "%d %f: ", &sv.Effects[idx].type, &sv.Effects[idx].expire_time); switch (sv.Effects[idx].type) { case CE_RAIN: fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.min_org[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.min_org[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.min_org[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.max_org[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.max_org[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.max_org[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.e_size[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.e_size[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.e_size[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.dir[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.dir[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.dir[2]); fscanf(FH, "%d ", &sv.Effects[idx].ef.Rain.color); fscanf(FH, "%d ", &sv.Effects[idx].ef.Rain.count); fscanf(FH, "%f\n", &sv.Effects[idx].ef.Rain.wait); break; case CE_SNOW: fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.min_org[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.min_org[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.min_org[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.max_org[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.max_org[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.max_org[2]); fscanf(FH, "%d ", &sv.Effects[idx].ef.Rain.flags); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.dir[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.dir[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Rain.dir[2]); fscanf(FH, "%d ", &sv.Effects[idx].ef.Rain.count); //fscanf(FH, "%d ", &sv.Effects[idx].ef.Rain.veer); /* O.S: a linefeed is missing here. not adding it so as not to break existing saves. also see in: SV_SaveEffects(). */ break; case CE_FOUNTAIN: fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.pos[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.pos[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.pos[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.angle[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.angle[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.angle[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.movedir[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.movedir[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Fountain.movedir[2]); fscanf(FH, "%d ", &sv.Effects[idx].ef.Fountain.color); fscanf(FH, "%d\n", &sv.Effects[idx].ef.Fountain.cnt); break; case CE_QUAKE: fscanf(FH, "%f ", &sv.Effects[idx].ef.Quake.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Quake.origin[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Quake.origin[2]); fscanf(FH, "%f\n", &sv.Effects[idx].ef.Quake.radius); 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_ACID_MUZZFL: case CE_FLAMESTREAM: case CE_FLAMEWALL: case CE_FLAMEWALL2: case CE_ONFIRE: fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.origin[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.origin[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.velocity[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.velocity[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.velocity[2]); /* smoke frame is a mission pack thing only: read carefully... */ // fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.framelength); // fscanf(FH, "%f\n", &sv.Effects[idx].ef.Smoke.frame); fscanf(FH, "%f", &sv.Effects[idx].ef.Smoke.framelength); c = fgetc (FH); /* read one char, see what it is: */ if (c == '\n' || c == '\r') { /* 1.11 style */ sv.Effects[idx].ef.Smoke.frame = 0; /* read one char until it's not an EOL char, then go one char back to the correct position. */ while (!feof(FH) && (c == '\n' || c == '\r')) c = fgetc (FH); if (!feof(FH)) ungetc (c, FH); } else { /* 1.12 mission pack style */ //if (c != ' ') // Sys_DPrintf ("broken save ??\n"); fscanf(FH, " %f\n", &sv.Effects[idx].ef.Smoke.frame); } 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_BRN_BOUNCE: case CE_LSHOCK: case CE_ACID_HIT: case CE_ACID_SPLAT: case CE_ACID_EXPL: case CE_LBALL_EXPL: case CE_FBOOM: case CE_FIREWALL_SMALL: case CE_FIREWALL_MEDIUM: case CE_FIREWALL_LARGE: case CE_BOMB: fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Smoke.origin[1]); fscanf(FH, "%f\n", &sv.Effects[idx].ef.Smoke.origin[2]); break; case CE_WHITE_FLASH: case CE_BLUE_FLASH: case CE_SM_BLUE_FLASH: case CE_RED_FLASH: fscanf(FH, "%f ", &sv.Effects[idx].ef.Flash.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Flash.origin[1]); fscanf(FH, "%f\n", &sv.Effects[idx].ef.Flash.origin[2]); break; case CE_RIDER_DEATH: fscanf(FH, "%f ", &sv.Effects[idx].ef.RD.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.RD.origin[1]); fscanf(FH, "%f\n", &sv.Effects[idx].ef.RD.origin[2]); break; case CE_GRAVITYWELL: fscanf(FH, "%f ", &sv.Effects[idx].ef.RD.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.RD.origin[1]); fscanf(FH, "%f", &sv.Effects[idx].ef.RD.origin[2]); fscanf(FH, "%d", &sv.Effects[idx].ef.RD.color); fscanf(FH, "%f\n", &sv.Effects[idx].ef.RD.lifetime); break; case CE_TELEPORTERPUFFS: fscanf(FH, "%f ", &sv.Effects[idx].ef.Teleporter.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Teleporter.origin[1]); fscanf(FH, "%f\n", &sv.Effects[idx].ef.Teleporter.origin[2]); break; case CE_TELEPORTERBODY: fscanf(FH, "%f ", &sv.Effects[idx].ef.Teleporter.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Teleporter.origin[1]); fscanf(FH, "%f\n", &sv.Effects[idx].ef.Teleporter.origin[2]); break; case CE_BONESHARD: case CE_BONESHRAPNEL: fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.origin[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.origin[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.velocity[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.velocity[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.velocity[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.angle[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.angle[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.angle[2]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.avelocity[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.avelocity[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Missile.avelocity[2]); /* O.S: a linefeed is missing here. not adding it so as not to break existing saves. also see in: SV_SaveEffects(). */ break; case CE_CHUNK: fscanf(FH, "%f ", &sv.Effects[idx].ef.Chunk.origin[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Chunk.origin[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Chunk.origin[2]); fscanf(FH, "%u ", &u); sv.Effects[idx].ef.Chunk.type = u & 0xff; fscanf(FH, "%f ", &sv.Effects[idx].ef.Chunk.srcVel[0]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Chunk.srcVel[1]); fscanf(FH, "%f ", &sv.Effects[idx].ef.Chunk.srcVel[2]); fscanf(FH, "%u ", &u); sv.Effects[idx].ef.Chunk.numChunks = u & 0xff; /* O.S: a linefeed is missing here. not adding it so as not to break existing saves. also see in: SV_SaveEffects(). */ break; default: Host_Error ("%s: bad type", __thisfunc__); break; } } }
// All changes need to be in SV_SendEffect(), SV_ParseEffect(), // SV_SaveEffects(), SV_LoadEffects(), CL_ParseEffect() void SV_LoadEffects(FILE *FH) { int index,Total,count; // Since the map is freshly loaded, clear out any effects as a result of // the loading SV_ClearEffects(); fscanf(FH,"Effects: %d\n",&Total); for(count=0;count<Total;count++) { fscanf(FH,"Effect: %d ",&index); fscanf(FH,"%d %f: ",&sv.Effects[index].type,&sv.Effects[index].expire_time); switch(sv.Effects[index].type) { case CE_RAIN: fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[0]); fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[1]); fscanf(FH, "%f ", &sv.Effects[index].Rain.min_org[2]); fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[0]); fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[1]); fscanf(FH, "%f ", &sv.Effects[index].Rain.max_org[2]); fscanf(FH, "%f ", &sv.Effects[index].Rain.e_size[0]); fscanf(FH, "%f ", &sv.Effects[index].Rain.e_size[1]); fscanf(FH, "%f ", &sv.Effects[index].Rain.e_size[2]); fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[0]); fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[1]); fscanf(FH, "%f ", &sv.Effects[index].Rain.dir[2]); fscanf(FH, "%d ", &sv.Effects[index].Rain.color); fscanf(FH, "%d ", &sv.Effects[index].Rain.count); fscanf(FH, "%f\n", &sv.Effects[index].Rain.wait); break; case CE_FOUNTAIN: fscanf(FH, "%f ", &sv.Effects[index].Fountain.pos[0]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.pos[1]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.pos[2]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.angle[0]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.angle[1]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.angle[2]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.movedir[0]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.movedir[1]); fscanf(FH, "%f ", &sv.Effects[index].Fountain.movedir[2]); fscanf(FH, "%d ", &sv.Effects[index].Fountain.color); fscanf(FH, "%d\n", &sv.Effects[index].Fountain.cnt); break; case CE_QUAKE: fscanf(FH, "%f ", &sv.Effects[index].Quake.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Quake.origin[1]); fscanf(FH, "%f ", &sv.Effects[index].Quake.origin[2]); fscanf(FH, "%f\n", &sv.Effects[index].Quake.radius); 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_ACID_MUZZFL: case CE_FLAMESTREAM: case CE_FLAMEWALL: case CE_FLAMEWALL2: case CE_ONFIRE: case CE_RIPPLE: fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[1]); fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[2]); fscanf(FH, "%f ", &sv.Effects[index].Smoke.velocity[0]); fscanf(FH, "%f ", &sv.Effects[index].Smoke.velocity[1]); fscanf(FH, "%f ", &sv.Effects[index].Smoke.velocity[2]); fscanf(FH, "%f\n", &sv.Effects[index].Smoke.framelength); 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_BRN_BOUNCE: case CE_LSHOCK: case CE_ACID_HIT: case CE_ACID_SPLAT: case CE_ACID_EXPL: case CE_LBALL_EXPL: case CE_FBOOM: case CE_FIREWALL_SMALL: case CE_FIREWALL_MEDIUM: case CE_FIREWALL_LARGE: case CE_BOMB: fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Smoke.origin[1]); fscanf(FH, "%f\n", &sv.Effects[index].Smoke.origin[2]); break; case CE_WHITE_FLASH: case CE_BLUE_FLASH: case CE_SM_BLUE_FLASH: case CE_HWSPLITFLASH: case CE_RED_FLASH: fscanf(FH, "%f ", &sv.Effects[index].Flash.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Flash.origin[1]); fscanf(FH, "%f\n", &sv.Effects[index].Flash.origin[2]); break; case CE_RIDER_DEATH: fscanf(FH, "%f ", &sv.Effects[index].RD.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].RD.origin[1]); fscanf(FH, "%f\n", &sv.Effects[index].RD.origin[2]); break; case CE_TELEPORTERPUFFS: fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[1]); fscanf(FH, "%f\n", &sv.Effects[index].Teleporter.origin[2]); break; case CE_TELEPORTERBODY: fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Teleporter.origin[1]); fscanf(FH, "%f\n", &sv.Effects[index].Teleporter.origin[2]); break; case CE_BONESHRAPNEL: case CE_HWBONEBALL: fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[2]); fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[2]); fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[2]); fscanf(FH, "%f ", &sv.Effects[index].Missile.avelocity[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.avelocity[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.avelocity[2]); break; case CE_BONESHARD: case CE_HWRAVENSTAFF: case CE_HWRAVENPOWER: case CE_HWMISSILESTAR: case CE_HWEIDOLONSTAR: fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[2]); fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.velocity[2]); break; case CE_DEATHBUBBLES: fscanf(FH, "%f ", &sv.Effects[index].Bubble.offset[0]); fscanf(FH, "%f ", &sv.Effects[index].Bubble.offset[1]); fscanf(FH, "%f ", &sv.Effects[index].Bubble.offset[2]); fscanf(FH, "%f ", &sv.Effects[index].Bubble.owner); fscanf(FH, "%f ", &sv.Effects[index].Bubble.count); break; case CE_HWDRILLA: fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.origin[2]); fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[0]); fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[1]); fscanf(FH, "%f ", &sv.Effects[index].Missile.angle[2]); fscanf(FH, "%f ", &sv.Effects[index].Missile.speed); break; case CE_SCARABCHAIN: fscanf(FH, "%f ", &sv.Effects[index].Chain.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Chain.origin[1]); fscanf(FH, "%f ", &sv.Effects[index].Chain.origin[2]); fscanf(FH, "%f ", &sv.Effects[index].Chain.owner); fscanf(FH, "%f ", &sv.Effects[index].Chain.material); fscanf(FH, "%f ", &sv.Effects[index].Chain.tag); break; case CE_HWSHEEPINATOR: case CE_HWXBOWSHOOT: fscanf(FH, "%f ", &sv.Effects[index].Xbow.origin[5][0]); fscanf(FH, "%f ", &sv.Effects[index].Xbow.origin[5][1]); fscanf(FH, "%f ", &sv.Effects[index].Xbow.origin[5][2]); fscanf(FH, "%f ", &sv.Effects[index].Xbow.angle[0]); fscanf(FH, "%f ", &sv.Effects[index].Xbow.angle[1]); fscanf(FH, "%f ", &sv.Effects[index].Xbow.angle[2]); fscanf(FH, "%f ", &sv.Effects[index].Xbow.bolts); fscanf(FH, "%f ", &sv.Effects[index].Xbow.activebolts); fscanf(FH, "%f ", &sv.Effects[index].Xbow.turnedbolts); break; case CE_TRIPMINESTILL: case CE_TRIPMINE: fscanf(FH, "%f ", &sv.Effects[index].Chain.origin[0]); fscanf(FH, "%f ", &sv.Effects[index].Chain.origin[1]); fscanf(FH, "%f ", &sv.Effects[index].Chain.origin[2]); fscanf(FH, "%f ", &sv.Effects[index].Chain.velocity[0]); fscanf(FH, "%f ", &sv.Effects[index].Chain.velocity[1]); fscanf(FH, "%f ", &sv.Effects[index].Chain.velocity[2]); break; default: PR_RunError ("SV_SaveEffect: bad type"); break; } } }