void DThinker::RunThinkers () { int i, count; ThinkCycles.Reset(); BotSupportCycles.Reset(); BotWTG = 0; ThinkCycles.Clock(); // Tick every thinker left from last time for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i) { TickThinkers (&Thinkers[i], NULL); } // Keep ticking the fresh thinkers until there are no new ones. do { count = 0; for (i = STAT_FIRST_THINKING; i <= MAX_STATNUM; ++i) { count += TickThinkers (&FreshThinkers[i], &Thinkers[i]); } } while (count != 0); ThinkCycles.Unclock(); }
bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret) { if (ActionFunc != nullptr) { ActionCycles.Clock(); VMValue params[3] = { self, stateowner, VMValue(info) }; // If the function returns a state, store it at *stateret. // If it doesn't return a state but stateret is non-nullptr, we need // to set *stateret to nullptr. if (stateret != nullptr) { *stateret = nullptr; if (ActionFunc->Proto == nullptr || ActionFunc->Proto->ReturnTypes.Size() == 0 || ActionFunc->Proto->ReturnTypes[0] != TypeState) { stateret = nullptr; } } try { if (stateret == nullptr) { VMCall(ActionFunc, params, ActionFunc->ImplicitArgs, nullptr, 0); } else { VMReturn ret; ret.PointerAt((void **)stateret); VMCall(ActionFunc, params, ActionFunc->ImplicitArgs, &ret, 1); } } catch (CVMAbortException &err) { err.MaybePrintMessage(); const char *callinfo = ""; if (info != nullptr && info->mStateType == STATE_Psprite) { if (stateowner->IsKindOf(NAME_Weapon) && stateowner != self) callinfo = "weapon "; else callinfo = "overlay "; } err.stacktrace.AppendFormat("Called from %sstate %s in %s\n", callinfo, FState::StaticGetStateName(this).GetChars(), stateowner->GetClass()->TypeName.GetChars()); throw; throw; } ActionCycles.Unclock(); return true; } else { return false; } }
bool FState::CallAction(AActor *self, AActor *stateowner, FStateParamInfo *info, FState **stateret) { if (ActionFunc != NULL) { ActionCycles.Clock(); static VMFrameStack stack; VMValue params[3] = { self, stateowner, VMValue(info, ATAG_STATEINFO) }; // If the function returns a state, store it at *stateret. // If it doesn't return a state but stateret is non-NULL, we need // to set *stateret to NULL. if (stateret != NULL) { *stateret = NULL; if (ActionFunc->Proto == NULL || ActionFunc->Proto->ReturnTypes.Size() == 0 || ActionFunc->Proto->ReturnTypes[0] != TypeState) { stateret = NULL; } } if (stateret == NULL) { stack.Call(ActionFunc, params, countof(params), NULL, 0, NULL); } else { VMReturn ret; ret.PointerAt((void **)stateret); stack.Call(ActionFunc, params, countof(params), &ret, 1, NULL); } ActionCycles.Unclock(); return true; } else { return false; } }
//This function is called every tick (from g_game.c). void FCajunMaster::Main () { BotThinkCycles.Reset(); if (demoplayback || gamestate != GS_LEVEL || consoleplayer != Net_Arbitrator) return; //Add new bots? if (wanted_botnum > botnum && !freeze) { if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY)) { if (!SpawnBot (getspawned[spawn_tries])) wanted_botnum--; spawn_tries++; } t_join--; } //Check if player should go observer. Or un observe FLinkContext ctx; if (bot_observer && !observer && !netgame) { Printf ("%s is now observer\n", players[consoleplayer].userinfo.GetName()); observer = true; players[consoleplayer].mo->UnlinkFromWorld (&ctx); players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY; players[consoleplayer].mo->flags2 |= MF2_FLY; players[consoleplayer].mo->LinkToWorld (&ctx); } else if (!bot_observer && observer && !netgame) //Go back { Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.GetName()); observer = false; players[consoleplayer].mo->UnlinkFromWorld (&ctx); players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY; players[consoleplayer].mo->flags2 &= ~MF2_FLY; players[consoleplayer].mo->LinkToWorld (&ctx); } }
//This function is called every tick (from g_game.c), //send bots into thinking (+more). void FCajunMaster::Main (int buf) { int i; BotThinkCycles.Reset(); if (consoleplayer != Net_Arbitrator || demoplayback) return; if (gamestate != GS_LEVEL) return; m_Thinking = true; //Think for bots. if (botnum) { BotThinkCycles.Clock(); for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].mo && !freeze && players[i].isbot) Think (players[i].mo, &netcmds[i][buf]); } BotThinkCycles.Unclock(); } //Add new bots? if (wanted_botnum > botnum && !freeze) { if (t_join == ((wanted_botnum - botnum) * SPAWN_DELAY)) { if (!SpawnBot (getspawned[spawn_tries])) wanted_botnum--; spawn_tries++; } t_join--; } //Check if player should go observer. Or un observe if (bot_observer && !observer && !netgame) { Printf ("%s is now observer\n", players[consoleplayer].userinfo.netname); observer = true; players[consoleplayer].mo->UnlinkFromWorld (); players[consoleplayer].mo->flags = MF_DROPOFF|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOTDMATCH|MF_NOGRAVITY|MF_FRIENDLY; players[consoleplayer].mo->flags2 |= MF2_FLY; players[consoleplayer].mo->LinkToWorld (); } else if (!bot_observer && observer && !netgame) //Go back { Printf ("%s returned to the fray\n", players[consoleplayer].userinfo.netname); observer = false; players[consoleplayer].mo->UnlinkFromWorld (); players[consoleplayer].mo->flags = MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY; players[consoleplayer].mo->flags2 &= ~MF2_FLY; players[consoleplayer].mo->LinkToWorld (); } m_Thinking = false; }