Skip to content

Commit

Permalink
Implement prototype scripting system
Browse files Browse the repository at this point in the history
  • Loading branch information
SamVanheer committed Nov 13, 2023
1 parent 9e270e7 commit 8bcd7c9
Show file tree
Hide file tree
Showing 47 changed files with 5,453 additions and 92 deletions.
1 change: 1 addition & 0 deletions src/game/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ target_sources(server PRIVATE
../../public/steam/steamtypes.h)

add_game_shared_sources(server)
add_subdirectory(scripting/AS)

target_precompile_headers(server PRIVATE entities/cbase.h)

Expand Down
15 changes: 15 additions & 0 deletions src/game/server/ServerLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@

#include "networking/NetworkDataSystem.h"

#include "scripting/AS/ASScriptingSystem.h"
#include "scripting/AS/ScriptConsoleCommands.h"
#include "scripting/AS/ScriptsSection.h"

#include "sound/MaterialSystem.h"
#include "sound/SentencesSystem.h"
#include "sound/ServerSoundSystem.h"
Expand Down Expand Up @@ -201,6 +205,8 @@ void ServerLibrary::RunFrame()

g_Bots.RunFrame();

scripting::g_Scripting.RunFrame();

// If we're loading all maps then change maps after 3 seconds (time starts at 1)
// to give the game time to generate files.
if (!m_MapsToLoad.empty() && gpGlobals->time > 4)
Expand Down Expand Up @@ -283,6 +289,9 @@ void ServerLibrary::NewMapStarted(bool loadGame)
list->Clear();
}

// Must be done before loading config files.
scripting::g_Scripting.NewMapStarted();

ClearStringPool();

// Initialize map state to its default state
Expand Down Expand Up @@ -318,6 +327,8 @@ void ServerLibrary::NewMapStarted(bool loadGame)
// Reset sky name to its default value. If the map specifies its own sky
// it will be set in CWorld::KeyValue or restored by the engine on save game load.
CVAR_SET_STRING("sv_skyname", DefaultSkyName);

scripting::g_Scripting.PostNewMapStarted();
}

void ServerLibrary::PreMapActivate()
Expand Down Expand Up @@ -391,6 +402,8 @@ void ServerLibrary::AddGameSystems()
g_GameSystems.Add(&g_MapCycleSystem);
g_GameSystems.Add(&g_EntityTemplates);
g_GameSystems.Add(&g_Bots);
g_GameSystems.Add(&scripting::g_Scripting);
g_GameSystems.Add(scripting::g_ScriptConCommands.get());
}

void ServerLibrary::SetEntLogLevels(spdlog::level::level_enum level)
Expand Down Expand Up @@ -439,6 +452,8 @@ void ServerLibrary::CreateConfigDefinitions()
sections.push_back(std::make_unique<GlobalSentenceReplacementSection>());
sections.push_back(std::make_unique<GlobalSoundReplacementSection>());
sections.push_back(std::make_unique<HudColorSection>());
// Only this config can specify scripts. For other configs, use plugins instead.
sections.push_back(std::make_unique<scripting::ScriptsSection<ServerConfigContext>>());
sections.push_back(std::make_unique<SuitLightTypeSection>());
sections.push_back(std::make_unique<SpawnInventorySection>());
sections.push_back(std::make_unique<EntityTemplatesSection>());
Expand Down
87 changes: 87 additions & 0 deletions src/game/server/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@

#include "ctf/ctf_goals.h"

#include "scripting/AS/ASScriptingSystem.h"
#include "scripting/AS/EventSystem.h"
#include "scripting/AS/ScriptAPI/Events.h"

unsigned int g_ulFrameCount;

/**
Expand Down Expand Up @@ -365,6 +369,16 @@ void Host_Say(CBasePlayer* player, bool teamonly)
if (!p || '\0' == p[0] || !Q_UnicodeValidate(p))
return; // no character found, so say nothing

// Inform plugins, see if any of them want to handle it.
{
const auto event = scripting::g_Scripting.GetEventSystem()->Publish<scripting::SayTextEventArgs>(p, pcmd);

if (event->Suppress)
{
return;
}
}

// turn on color set 2 (color on, no sound)
// turn on color set 2 (color on, no sound)
if (player->IsObserver() && (teamonly))
Expand Down Expand Up @@ -1002,6 +1016,79 @@ void SV_CreateClientCommands()
}
} },
{.Flags = ClientCommandFlag::Cheat});

g_ClientCommands.Create("ent_create_custom", [](CBasePlayer* player, const CommandArgs& args)
{
if (args.Count() < 2)
{
UTIL_ConsolePrint(player, "usage: ent_create_custom <classname>\n");
return;
}

UTIL_MakeVectors(player->pev->v_angle);

const auto start = player->pev->origin + player->pev->view_ofs;

TraceResult tr;

UTIL_TraceLine(start, start + gpGlobals->v_forward * 8192, dont_ignore_monsters, player->edict(), &tr);

if (tr.fStartSolid != 0 || tr.fAllSolid != 0)
{
UTIL_ConsolePrint(player, "No room to spawn entity\n");
return;
}

auto entity = CBaseEntity::Create("custom", tr.vecEndPos, vec3_origin, nullptr, false);

if (FNullEnt(entity))
{
CBaseEntity::Logger->debug("NULL Ent in ent_create_custom!\n");
return;
}

KeyValueData kvd;

kvd.szClassName = "custom";
kvd.szKeyName = "customclass";
kvd.szValue = args.Argument(1);
kvd.fHandled = 0;

// Do not access the CBaseEntity pointer after passing in the class name
// The entity object is destroyed and replaced with the C++ wrapper so the pointer will become invalid.
auto edict = entity->edict();

DispatchKeyValue(edict, &kvd);
DispatchSpawn(edict);

if (kvd.fHandled == 0 || (edict->v.flags & FL_KILLME) != 0)
{
return;
}

entity = GET_PRIVATE<CBaseEntity>(edict);

if (!entity)
{
return;
}

// Move NPC up based on its bounding box.
if (entity->pev->mins.z < 0)
{
entity->pev->origin.z -= entity->pev->mins.z;
}

if ((entity->pev->flags & FL_FLY) == 0 && entity->pev->movetype != MOVETYPE_FLY)
{
// See if the NPC is stuck in something.
if (DROP_TO_FLOOR(entity->edict()) == 0)
{
UTIL_ConsolePrint(player, "NPC fell out of level\n");
UTIL_Remove(entity);
}
} },
{.Flags = ClientCommandFlag::Cheat});
}

bool UTIL_CheatsAllowed(CBasePlayer* player, std::string_view name)
Expand Down
16 changes: 16 additions & 0 deletions src/game/server/entities/CBaseEntity.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@

#include <spdlog/logger.h>

#include <angelscript/scriptdictionary/scriptdictionary.h>

#include "Platform.h"
#include "extdll.h"
#include "util.h"
#include "DataMap.h"
#include "EntityClassificationSystem.h"
#include "skill.h"

#include "scripting/AS/as_utils.h"

class CBaseEntity;
class CBaseItem;
class CBaseMonster;
Expand All @@ -38,6 +42,11 @@ class CTalkMonster;
class CItemCTF;
struct ReplacementMap;

namespace scripting
{
class ICustomEntity;
}

#define MAX_PATH_SIZE 10 // max number of nodes available for a path.

// These are caps bits to indicate what an object's capabilities (currently used for save/restore and level transitions)
Expand Down Expand Up @@ -314,12 +323,15 @@ class SINGLE_INHERITANCE CBaseEntity
virtual int BloodColor() { return DONT_BLEED; }
virtual void TraceBleed(float flDamage, Vector vecDir, TraceResult* ptr, int bitsDamageType);
virtual bool IsTriggered(CBaseEntity* pActivator) { return true; }

virtual CBaseMonster* MyMonsterPointer() { return nullptr; }
virtual CTalkMonster* MyTalkMonsterPointer() { return nullptr; }
virtual CSquadMonster* MySquadMonsterPointer() { return nullptr; }
virtual COFSquadTalkMonster* MySquadTalkMonsterPointer() { return nullptr; }
virtual CBaseItem* MyItemPointer() { return nullptr; }
virtual CItemCTF* MyItemCTFPointer() { return nullptr; }
virtual scripting::ICustomEntity* MyCustomEntityPointer() { return nullptr; }

virtual float GetDelay() { return 0; }
virtual bool IsMoving() { return pev->velocity != g_vecZero; }
virtual void OverrideReset() {}
Expand Down Expand Up @@ -617,6 +629,10 @@ class SINGLE_INHERITANCE CBaseEntity
* @details The entity's angles affect this offset.
*/
Vector m_SoundOffset{};

as::UniquePtr<CScriptDictionary> m_UserDataDictionary;

CScriptDictionary* GetUserData();
};

inline bool FNullEnt(CBaseEntity* ent) { return (ent == nullptr) || FNullEnt(ent->edict()); }
Expand Down
16 changes: 16 additions & 0 deletions src/game/server/entities/cbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@

#include <unordered_map>

#include <angelscript/scriptdictionary/scriptdictionary.h>

#include "cbase.h"
#include "ServerLibrary.h"
#include "pm_shared.h"
#include "world.h"
#include "scripting/AS/ASScriptingSystem.h"
#include "sound/ServerSoundSystem.h"
#include "utils/ReplacementMaps.h"

Expand Down Expand Up @@ -909,3 +912,16 @@ void CBaseEntity::StopSound(int channel, const char* sample)
{
sound::g_ServerSound.EmitSound(this, channel, sample, 0, 0, SND_STOP, PITCH_NORM);
}

CScriptDictionary* CBaseEntity::GetUserData()
{
// Lazily create to avoid wasting memory.
if (!m_UserDataDictionary)
{
m_UserDataDictionary.reset(CScriptDictionary::Create(scripting::g_Scripting.GetEngine()));
}

m_UserDataDictionary->AddRef();

return m_UserDataDictionary.get();
}
Loading

0 comments on commit 8bcd7c9

Please sign in to comment.