// Assign bitmask to each player to indicate what team they are in // Called at match start and also when a client connects void BotsAssignTeamFlags (void) { gedict_t *p, *p2; int teamflag = 1; char *s = ""; if (!teamplay) return; // Clear teamflag from all items for (p = world; (p = nextent (p)); ) p->fb.teamflag = 0; for ( p = world; (p = find_plr( p )); ) p->k_flag = 0; for ( p = world; (p = find_plr( p )); ) { if( p->k_flag || strnull( s = getteam( p ) ) ) continue; p->k_flag = 1; p->fb.teamflag = teamflag; for (p2 = p; (p2 = find_plr (p2)); ) { if (streq (s, getteam (p2))) { p2->k_flag = 1; p2->fb.teamflag = teamflag; } } teamflag <<= 1; } }
void LoadMap(void) { // Need to do this anyway, otherwise teleporters will be broken CreateItemMarkers(); if (!(isRACE () || isCTF ())) { // If we have a .bot file, use that if (LoadBotRoutingFromFile ()) { map_supported = true; CustomiseFrogbotMap (); AssignVirtualGoals (); AllMarkersLoaded (); return; } } // At this point it's an unsupported map CustomiseFrogbotMap (); if (FrogbotOptionEnabled (FB_OPTION_EDITOR_MODE)) { gedict_t* e; // We don't want spawnpoint markers or powerups to mess with colours for (e = world; (e = nextent (e)); ) { e->s.v.effects = (int)e->s.v.effects & ~(EF_BLUE | EF_GREEN | EF_RED); } AssignGoalNumbers (); } }
void View_UpdateEveryFrame() { local entity ent; ent = nextent(world); while (ent) { if (ent.classname == "player") { if (player.PersID == CLIENT_IDs) // YOURSELF { View_ThirdPerson (); } player.predraw = Player_AnimationBlendCyclesIQM; } else if (ent.classname == "enemy_base") { Enemy_FacingPlayer(ent); enemyBase.predraw = Enemy_Predraw; } ent = nextent(ent); } }
// After all markers have been created, re-process items static void AssignVirtualGoals(void) { gedict_t* item; for (item = world; (item = nextent(item)); ) { int i = 0; for (i = 0; i < ItemSpawnFunctionCount(); ++i) { fb_spawn_t* spawn = ItemSpawnFunction(i); if (streq(spawn->name, item->classname)) { AssignVirtualGoal_apply(item); break; } } } }
static void CreateItemMarkers() { // Old frogbot method was to call during item spawns, we just // catch up afterwards once we know the map is valid gedict_t* item; for (item = world; (item = nextent(item)); ) { int i = 0; qbool found = false; // Don't bother with search if it's already processed if (ProcessedItem(item)) { continue; } // check for item spawn for (i = 0; i < ItemSpawnFunctionCount(); ++i) { fb_spawn_t* spawn = ItemSpawnFunction (i); if (streq(spawn->name, item->classname)) { BecomeMarker (item); spawn->func(item); found = true; break; } } // check for std spawn (world items like buttons etc) if (! found) { for (i = 0; i < sizeof(stdSpawnFunctions) / sizeof(stdSpawnFunctions[0]); ++i) { if (streq(stdSpawnFunctions[i].name, item->classname)) { stdSpawnFunctions[i].func(item); found = true; break; } } } if (found && ProcessedItem(item)) { SpawnMarkerIndicator (item); } } }
// KTX has in-built modifications to several maps - frogbot routing relies on entity order so we have // to customise again here. Called after all markers created, but before traveltime calculations static void CustomiseFrogbotMap (void) { gedict_t* ent = NULL; // KTX may have added a quad, so to keep routes compatible with PR1-version, we add it as a marker after others if (streq(g_globalvars.mapname, "aerowalk") && !FrogbotOptionEnabled(FB_OPTION_EDITOR_MODE)) { gedict_t* quad = ez_find (world, "item_artifact_super_damage"); if (quad) { gedict_t* nearest_marker; quad->fb.fl_marker = false; nearest_marker = LocateMarker (quad->s.v.origin); quad->fb.fl_marker = true; StartItemFB (quad); quad->fb.T |= MARKER_DYNAMICALLY_ADDED; // Quad is in same zone as nearest marker, and linked by the first path that's valid SetZone (nearest_marker->fb.Z_, quad->fb.index + 1); SetGoalForMarker (18, quad); AddPath (nearest_marker, quad); AddPath (quad, nearest_marker); SpawnMarkerIndicator (quad); } } // We stopped it from removing the telespawn earlier on... if (!cvar ("k_end_tele_spawn") && streq ("end", g_globalvars.mapname)) { vec3_t TS_ORIGIN = { -392, 608, 40 }; // tele spawn gedict_t* p = NULL; gedict_t* m = NULL; for (p = world; (p = find (p, FOFCLSN, "info_player_deathmatch")); ) { if (VectorCompare (p->s.v.origin, TS_ORIGIN)) { p->classname = "info_player_deathmatch_removed"; // Remove any spawn marker for (m = world; (m = find (m, FOFCLSN, "spawnpoint")); ) { if (m->k_lastspawn == p) { ent_remove (m); break; } } break; } } } // Expand bounding box of all items if (!isRACE()) { for (ent = world; (ent = nextent(ent)); ) { if (streq(ent->classname, "info_teleport_destination") || streq(ent->classname, "info_player_deathmatch")) { continue; } if (streq(ent->classname, "marker")) { vec3_t mins = { -65, -65, -24 }; vec3_t maxs = { 65, 65, 32 }; vec3_t viewoffset = { 80, 80, 24 }; int i; for (i = 0; i < 3; ++i) { if (ent->fb.fixed_size[i]) { mins[i] = -ent->fb.fixed_size[i] / 2 - (i < 2 ? 15 : 0); maxs[i] = ent->fb.fixed_size[i] / 2 - (i < 2 ? 15 : 0); viewoffset[i] = (maxs[i] - mins[i]) / 2; } } VectorCopy(viewoffset, ent->s.v.view_ofs); setsize(ent, PASSVEC3(mins), PASSVEC3(maxs)); } else if ((int)ent->s.v.flags & FL_ITEM) { PlaceItemFB(ent); } } } // Link all teleporters if (FrogbotOptionEnabled (FB_OPTION_EDITOR_MODE)) { for (ent = world; (ent = ez_find (ent, "trigger_teleport")); ) { // If this teleport takes us to the marker close to the grenade, set arrow_time if (!strnull (ent->target)) { gedict_t* target = find (world, FOFS (targetname), ent->target); AddPath (ent, target); } } } }