/* ================= ReadLevel SpawnEntities will already have been called on the level the same way it was when the level was saved. That is necessary to get the baselines set up identically. The server will have cleared all of the world links before calling ReadLevel. No clients are connected yet. ================= */ void ReadLevel (char *filename) { int entnum; FILE *f; int i; void *base; edict_t *ent; f = fopen (filename, "rb"); if (!f) gi.error ("Couldn't open %s", filename); // free any dynamic memory allocated by loading the level // base state gi.FreeTags (TAG_LEVEL); // wipe all the entities memset (g_edicts, 0, game.maxentities * sizeof (g_edicts[0])); globals.num_edicts = maxclients->value + 1; // check edict size fread (&i, sizeof (i), 1, f); if (i != sizeof (edict_t)) { fclose (f); gi.error ("ReadLevel: mismatched edict size"); } // check function pointer base address fread (&base, sizeof (base), 1, f); if (base != (void *) InitGame) { fclose (f); gi.error ("ReadLevel: function pointers have moved"); } // load the level locals ReadLevelLocals (f); // load all the entities while (1) { if (fread (&entnum, sizeof (entnum), 1, f) != 1) { fclose (f); gi.error ("ReadLevel: failed to read entnum"); } if (entnum == -1) break; if (entnum >= globals.num_edicts) globals.num_edicts = entnum + 1; ent = &g_edicts[entnum]; ReadEdict (f, ent); // let the server rebuild world links for this ent memset (&ent->area, 0, sizeof (ent->area)); gi.linkentity (ent); } fclose (f); // mark all clients as unconnected for (i = 0; i < maxclients->value; i++) { ent = &g_edicts[i + 1]; ent->client = game.clients + i; ent->client->pers.connected = false; } // do any load time things at this point for (i = 0; i < globals.num_edicts; i++) { ent = &g_edicts[i]; if (!ent->inuse) continue; // fire any cross-level triggers if (ent->classname && strcmp (ent->classname, "target_crosslevel_target") == 0) ent->nextthink = level.time + ent->delay; } }
void LoadTransitionEnts() { if(developer->value) gi.dprintf("==== LoadTransitionEnts ====\n"); if(game.transition_ents) { char t_file[_MAX_PATH]; int i, j; FILE *f; vec3_t v_spawn; edict_t *ent; edict_t *spawn; VectorClear(v_spawn); if(strlen(game.spawnpoint)) { spawn = G_Find(NULL,FOFS(targetname),game.spawnpoint); while(spawn) { if(!Q_stricmp(spawn->classname,"info_player_start")) { VectorCopy(spawn->s.origin,v_spawn); break; } spawn = G_Find(spawn,FOFS(targetname),game.spawnpoint); } } trans_ent_filename (t_file); f = fopen(t_file,"rb"); if(!f) gi.error("LoadTransitionEnts: Cannot open %s\n",t_file); else { for(i=0; i<game.transition_ents; i++) { ent = G_Spawn(); ReadEdict(f,ent); // Correction for monsters with health EXACTLY 0 // If we don't do this, spawn function will bring // 'em back to life if(ent->svflags & SVF_MONSTER) { if(!ent->health) { ent->health = -1; ent->deadflag = DEAD_DEAD; } else if(ent->deadflag == DEAD_DEAD) { ent->health = min(ent->health,-1); } } VectorAdd(ent->s.origin,v_spawn,ent->s.origin); VectorCopy(ent->s.origin,ent->s.old_origin); ED_CallSpawn (ent); if(ent->owner_id) { if(ent->owner_id < 0) { ent->owner = &g_edicts[-ent->owner_id]; } else { // We KNOW owners precede owned ents in the // list because of the way it was constructed ent->owner = NULL; for(j=game.maxclients+1; j<globals.num_edicts && !ent->owner; j++) { if(ent->owner_id == g_edicts[j].id) ent->owner = &g_edicts[j]; } } ent->owner_id = 0; } ent->s.renderfx |= RF_IR_VISIBLE; } fclose(f); } } }
/* * Reads a level back into the memory. * SpawnEntities were already called * in the same way when the level was * saved. All world links were cleared * before this function was called. When * this function is called, no clients * are connected to the server. */ void ReadLevel(const char *filename) { int entnum; FILE *f; int i; edict_t *ent; f = fopen(filename, "rb"); if (!f) { gi.error("Couldn't open %s", filename); } /* free any dynamic memory allocated by loading the level base state */ gi.FreeTags(TAG_LEVEL); /* wipe all the entities */ memset(g_edicts, 0, game.maxentities * sizeof(g_edicts[0])); globals.num_edicts = maxclients->value + 1; /* check edict size */ fread(&i, sizeof(i), 1, f); if (i != sizeof(edict_t)) { fclose(f); gi.error("ReadLevel: mismatched edict size"); } /* load the level locals */ ReadLevelLocals(f); /* load all the entities */ while (1) { if (fread(&entnum, sizeof(entnum), 1, f) != 1) { fclose(f); gi.error("ReadLevel: failed to read entnum"); } if (entnum == -1) { break; } if (entnum >= globals.num_edicts) { globals.num_edicts = entnum + 1; } ent = &g_edicts[entnum]; ReadEdict(f, ent); /* let the server rebuild world links for this ent */ memset(&ent->area, 0, sizeof(ent->area)); gi.linkentity(ent); } fclose(f); /* mark all clients as unconnected */ for (i = 0; i < maxclients->value; i++) { ent = &g_edicts[i + 1]; ent->client = game.clients + i; ent->client->pers.connected = false; } /* do any load time things at this point */ for (i = 0; i < globals.num_edicts; i++) { ent = &g_edicts[i]; if (!ent->inuse) { continue; } /* fire any cross-level triggers */ if (ent->classname) { if (strcmp(ent->classname, "target_crosslevel_target") == 0) { ent->nextthink = level.time + ent->delay; } } } }
void ReadLevel (char *filename) { int entnum; FILE *f; int i; void *base; edict_t *ent; if(developer->value) gi.dprintf ("==== ReadLevel ====\n"); f = fopen (filename, "rb"); if (!f) gi.error ("Couldn't open %s", filename); // free any dynamic memory allocated by loading the level // base state gi.FreeTags (TAG_LEVEL); // wipe all the entities memset (g_edicts, 0, game.maxentities*sizeof(g_edicts[0])); globals.num_edicts = maxclients->value+1; // check edict size fread (&i, sizeof(i), 1, f); if (i != sizeof(edict_t)) { fclose (f); gi.error ("ReadLevel: mismatched edict size"); } // check function pointer base address fread (&base, sizeof(base), 1, f); /* Lazarus: The __DATE__ check in ReadGame is sufficient for a version check. The following is reported to fail under some circumstances (though I've never seen it). #ifdef _WIN32 if (base != (void *)InitGame) { fclose (f); gi.error ("ReadLevel: function pointers have moved"); } #else gi.dprintf("Function offsets %d\n", ((byte *)base) - ((byte *)InitGame)); #endif */ // load the level locals ReadLevelLocals (f); // load all the entities while (1) { if (fread (&entnum, sizeof(entnum), 1, f) != 1) { fclose (f); gi.error ("ReadLevel: failed to read entnum"); } if (entnum == -1) break; if (entnum >= globals.num_edicts) globals.num_edicts = entnum+1; ent = &g_edicts[entnum]; ReadEdict (f, ent); // let the server rebuild world links for this ent memset (&ent->area, 0, sizeof(ent->area)); gi.linkentity (ent); } fclose (f); // mark all clients as unconnected for (i=0 ; i<maxclients->value ; i++) { ent = &g_edicts[i+1]; ent->client = game.clients + i; ent->client->pers.connected = false; } // do any load time things at this point for (i=0 ; i<globals.num_edicts ; i++) { ent = &g_edicts[i]; if (!ent->inuse) continue; // fire any cross-level triggers if (ent->classname) if (strcmp(ent->classname, "target_crosslevel_target") == 0) ent->nextthink = level.time + ent->delay; } // DWH: Load transition entities if(game.transition_ents) { LoadTransitionEnts(); actor_files(); } }