mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-28 21:57:57 +03:00
Merge pull request #660 from smallmodel/scriptdelegate
Implement and use delegates
This commit is contained in:
commit
147678b0f0
21 changed files with 802 additions and 199 deletions
|
@ -1843,7 +1843,7 @@ void DM_Manager::BuildTeamInfo_ver6(DM_Team *dmTeam)
|
|||
for (int i = iNumPlayers; i > 0; i--) {
|
||||
pTeamPlayer = dmTeam->m_players.ObjectAt(i);
|
||||
|
||||
if (pTeamPlayer->IsSubclassOfBot()) {
|
||||
if (pTeamPlayer->edict->r.svFlags & SVF_BOT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1888,7 +1888,7 @@ void DM_Manager::BuildTeamInfo_ver15(DM_Team *dmTeam)
|
|||
for (int i = iNumPlayers; i > 0; i--) {
|
||||
pTeamPlayer = dmTeam->m_players.ObjectAt(i);
|
||||
|
||||
if (pTeamPlayer->IsSubclassOfBot()) {
|
||||
if (pTeamPlayer->edict->r.svFlags & SVF_BOT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1962,7 +1962,7 @@ void DM_Manager::BuildPlayerTeamInfo(DM_Team *dmTeam, int *iPlayerList, DM_Team
|
|||
pTeamPlayer->GetNumKills(),
|
||||
pTeamPlayer->GetNumDeaths(),
|
||||
G_TimeString(level.svsFloatTime - pTeamPlayer->edict->client->pers.enterTime),
|
||||
pTeamPlayer->IsSubclassOfBot() ? "bot" : va("%d", pTeamPlayer->client->ps.ping)
|
||||
(pTeamPlayer->edict->r.svFlags & SVF_BOT) ? "bot" : va("%d", pTeamPlayer->client->ps.ping)
|
||||
);
|
||||
} else {
|
||||
Com_sprintf(
|
||||
|
@ -1973,7 +1973,7 @@ void DM_Manager::BuildPlayerTeamInfo(DM_Team *dmTeam, int *iPlayerList, DM_Team
|
|||
pTeamPlayer->GetNumKills(),
|
||||
pTeamPlayer->GetNumDeaths(),
|
||||
G_TimeString(level.svsFloatTime - pTeamPlayer->edict->client->pers.enterTime),
|
||||
pTeamPlayer->IsSubclassOfBot() ? "bot" : va("%d", pTeamPlayer->client->ps.ping)
|
||||
(pTeamPlayer->edict->r.svFlags & SVF_BOT) ? "bot" : va("%d", pTeamPlayer->client->ps.ping)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -2673,7 +2673,7 @@ void Entity::DamageEvent(Event *ev)
|
|||
Vector momentum;
|
||||
Vector position, direction, normal;
|
||||
int knockback, damageflags, meansofdeath, location;
|
||||
Event *event;
|
||||
Event event;
|
||||
float m;
|
||||
EntityPtr This;
|
||||
|
||||
|
@ -2759,67 +2759,79 @@ void Entity::DamageEvent(Event *ev)
|
|||
|
||||
if (health <= 0) {
|
||||
if (attacker) {
|
||||
event = new Event(EV_GotKill);
|
||||
event->AddEntity(this);
|
||||
event->AddInteger(damage);
|
||||
event->AddEntity(inflictor);
|
||||
event->AddInteger(meansofdeath);
|
||||
event->AddInteger(0);
|
||||
const EntityPtr attackerPtr = attacker;
|
||||
|
||||
attacker->ProcessEvent(event);
|
||||
event = Event(EV_GotKill, 5);
|
||||
event.AddEntity(this);
|
||||
event.AddInteger(damage);
|
||||
event.AddEntity(inflictor);
|
||||
event.AddInteger(meansofdeath);
|
||||
event.AddInteger(0);
|
||||
|
||||
attackerPtr->ProcessEvent(event);
|
||||
if (attackerPtr) {
|
||||
attackerPtr->delegate_gotKill.Execute(event);
|
||||
}
|
||||
}
|
||||
|
||||
if (!This) {
|
||||
return;
|
||||
}
|
||||
|
||||
event = new Event(EV_Killed);
|
||||
event->AddEntity(attacker);
|
||||
event->AddFloat(damage);
|
||||
event->AddEntity(inflictor);
|
||||
event->AddVector(position);
|
||||
event->AddVector(direction);
|
||||
event->AddVector(normal);
|
||||
event->AddInteger(knockback);
|
||||
event->AddInteger(damageflags);
|
||||
event->AddInteger(meansofdeath);
|
||||
event->AddInteger(location);
|
||||
event = Event(EV_Killed, 10);
|
||||
event.AddEntity(attacker);
|
||||
event.AddFloat(damage);
|
||||
event.AddEntity(inflictor);
|
||||
event.AddVector(position);
|
||||
event.AddVector(direction);
|
||||
event.AddVector(normal);
|
||||
event.AddInteger(knockback);
|
||||
event.AddInteger(damageflags);
|
||||
event.AddInteger(meansofdeath);
|
||||
event.AddInteger(location);
|
||||
|
||||
ProcessEvent(event);
|
||||
|
||||
if (!This) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify scripts
|
||||
Unregister(STRING_DAMAGE);
|
||||
if (!This) {
|
||||
return;
|
||||
}
|
||||
|
||||
delegate_killed.Execute(event);
|
||||
return;
|
||||
}
|
||||
|
||||
event = new Event(EV_Pain);
|
||||
event->AddEntity(attacker);
|
||||
event->AddFloat(damage);
|
||||
event->AddEntity(inflictor);
|
||||
event->AddVector(position);
|
||||
event->AddVector(direction);
|
||||
event->AddVector(normal);
|
||||
event->AddInteger(knockback);
|
||||
event->AddInteger(damageflags);
|
||||
event->AddInteger(meansofdeath);
|
||||
event->AddInteger(location);
|
||||
event = Event(EV_Pain, 10);
|
||||
event.AddEntity(attacker);
|
||||
event.AddFloat(damage);
|
||||
event.AddEntity(inflictor);
|
||||
event.AddVector(position);
|
||||
event.AddVector(direction);
|
||||
event.AddVector(normal);
|
||||
event.AddInteger(knockback);
|
||||
event.AddInteger(damageflags);
|
||||
event.AddInteger(meansofdeath);
|
||||
event.AddInteger(location);
|
||||
|
||||
ProcessEvent(event);
|
||||
|
||||
if (!This) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Notify scripts
|
||||
Unregister(STRING_DAMAGE);
|
||||
if (!This) {
|
||||
return;
|
||||
}
|
||||
|
||||
delegate_damage.Execute(event);
|
||||
}
|
||||
|
||||
qboolean Entity::IsTouching(Entity *e1)
|
||||
|
||||
{
|
||||
if (e1->absmin.x > absmax.x) {
|
||||
return false;
|
||||
|
|
|
@ -51,6 +51,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#include "script.h"
|
||||
#include "listener.h"
|
||||
#include "simpleentity.h"
|
||||
#include "../qcommon/delegate.h"
|
||||
|
||||
// modification flags
|
||||
#define FLAG_IGNORE 0
|
||||
|
@ -296,6 +297,12 @@ public:
|
|||
//====
|
||||
#endif
|
||||
|
||||
MulticastDelegate<void (const Event& ev)> delegate_damage;
|
||||
MulticastDelegate<void (const Event& ev)> delegate_killed;
|
||||
MulticastDelegate<void (const Event& ev)> delegate_gotKill;
|
||||
|
||||
public:
|
||||
|
||||
Entity();
|
||||
virtual ~Entity();
|
||||
|
||||
|
|
|
@ -157,16 +157,16 @@ Begin spawning a new bot entity
|
|||
*/
|
||||
void G_BotBegin(gentity_t *ent)
|
||||
{
|
||||
PlayerBot *player;
|
||||
Player *player;
|
||||
BotController *controller;
|
||||
|
||||
level.spawn_entnum = ent->s.number;
|
||||
player = new PlayerBot;
|
||||
player = new Player;
|
||||
|
||||
G_ClientBegin(ent, NULL);
|
||||
|
||||
controller = botManager.getControllerManager().createController(player);
|
||||
player->setController(controller);
|
||||
//player->setController(controller);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -271,7 +271,7 @@ void G_BotShift(int clientNum)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ent->entity->IsSubclassOfBot()) {
|
||||
if (!botManager.getControllerManager().findController(ent->entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ bool G_IsBot(gentity_t *ent)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ent->entity || !ent->entity->IsSubclassOfBot()) {
|
||||
if (!ent->entity || !botManager.getControllerManager().findController(ent->entity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -375,7 +375,7 @@ bool G_IsPlayer(gentity_t *ent)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!ent->entity || ent->entity->IsSubclassOfBot()) {
|
||||
if (!ent->entity || botManager.getControllerManager().findController(ent->entity)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -827,6 +827,7 @@ void G_BotConnect(int clientNum, qboolean firstTime, const char *userinfo)
|
|||
|
||||
ent->client = game.clients + clientNum;
|
||||
ent->s.number = clientNum;
|
||||
ent->r.svFlags |= SVF_BOT;
|
||||
|
||||
client = ent->client;
|
||||
|
||||
|
|
|
@ -58,6 +58,12 @@ const Vector power_color(0.0, 1.0, 0.0);
|
|||
const Vector acolor(1.0, 1.0, 1.0);
|
||||
const Vector bcolor(1.0, 0.0, 0.0);
|
||||
|
||||
ScriptDelegate Player::scriptDelegate_connected("player_connected", "Sent once when the player connected");
|
||||
ScriptDelegate Player::scriptDelegate_disconnecting("player_disconnecting", "The player is disconnecting");
|
||||
ScriptDelegate Player::scriptDelegate_spawned("player_spawned", "The player has spawned");
|
||||
ScriptDelegate Player::scriptDelegate_damage("player_damage", "The player got hit");
|
||||
ScriptDelegate Player::scriptDelegate_kill("player_killed", "The player got killed");
|
||||
|
||||
//
|
||||
// mohaas 2.0 and above
|
||||
//
|
||||
|
@ -2264,6 +2270,8 @@ void Player::Init(void)
|
|||
|
||||
Event *ev = new Event;
|
||||
ev->AddEntity(this);
|
||||
|
||||
scriptDelegate_connected.Trigger(*ev);
|
||||
scriptedEvents[SE_CONNECTED].Trigger(ev);
|
||||
}
|
||||
|
||||
|
@ -3217,6 +3225,7 @@ void Player::Killed(Event *ev)
|
|||
event->AddInteger(ev->GetInteger(10));
|
||||
event->AddEntity(this);
|
||||
|
||||
scriptDelegate_kill.Trigger(*event);
|
||||
scriptedEvents[SE_KILL].Trigger(event);
|
||||
|
||||
Unregister(STRING_DEATH);
|
||||
|
@ -9704,14 +9713,16 @@ void Player::ArmorDamage(Event *ev)
|
|||
event->AddInteger(ev->GetInteger(10));
|
||||
event->AddEntity(this);
|
||||
|
||||
scriptDelegate_damage.Trigger(*event);
|
||||
scriptedEvents[SE_DAMAGE].Trigger(event);
|
||||
}
|
||||
|
||||
void Player::Disconnect(void)
|
||||
{
|
||||
Event *ev = new Event;
|
||||
|
||||
ev->AddListener(this);
|
||||
|
||||
scriptDelegate_disconnecting.Trigger(*ev);
|
||||
scriptedEvents[SE_DISCONNECTED].Trigger(ev);
|
||||
|
||||
// if (g_gametype->integer != GT_SINGLE_PLAYER) {
|
||||
|
@ -10429,9 +10440,12 @@ void Player::EventStuffText(Event *ev)
|
|||
Event *event = new Event(EV_Player_StuffText);
|
||||
event->AddValue(ev->GetValue(1));
|
||||
PostEvent(event, level.frametime, 0);
|
||||
} else {
|
||||
gi.SendServerCommand(edict - g_entities, "stufftext \"%s\"", ev->GetString(1).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
gi.SendServerCommand(edict - g_entities, "stufftext \"%s\"", ev->GetString(1).c_str());
|
||||
|
||||
delegate_stufftext.Execute(ev->GetString(1));
|
||||
}
|
||||
|
||||
void Player::EventSetVoiceType(Event *ev)
|
||||
|
@ -12084,8 +12098,9 @@ bool Player::IsReady(void) const
|
|||
void Player::Spawned(void)
|
||||
{
|
||||
Event *ev = new Event;
|
||||
|
||||
ev->AddEntity(this);
|
||||
|
||||
scriptDelegate_spawned.Trigger(*ev);
|
||||
scriptedEvents[SE_SPAWN].Trigger(ev);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
#include "actor.h"
|
||||
#include "vehicle.h"
|
||||
#include "dm_manager.h"
|
||||
#include "scriptdelegate.h"
|
||||
|
||||
extern Event EV_Player_EndLevel;
|
||||
extern Event EV_Player_GiveCheat;
|
||||
|
@ -310,6 +311,15 @@ private:
|
|||
bool m_bShowingHint;
|
||||
#endif
|
||||
|
||||
public:
|
||||
MulticastDelegate<void (const str& text)> delegate_stufftext;
|
||||
|
||||
static ScriptDelegate scriptDelegate_connected;
|
||||
static ScriptDelegate scriptDelegate_disconnecting;
|
||||
static ScriptDelegate scriptDelegate_spawned;
|
||||
static ScriptDelegate scriptDelegate_damage;
|
||||
static ScriptDelegate scriptDelegate_kill;
|
||||
|
||||
public:
|
||||
int m_iNumObjectives;
|
||||
int m_iObjectivesCompleted;
|
||||
|
|
|
@ -76,6 +76,15 @@ BotController::BotController()
|
|||
m_RunLabel.TrySetScript("global/bot_run.scr");
|
||||
}
|
||||
|
||||
BotController::~BotController()
|
||||
{
|
||||
if (controlledEnt) {
|
||||
controlledEnt->delegate_gotKill.Remove(delegateHandle_gotKill);
|
||||
controlledEnt->delegate_killed.Remove(delegateHandle_killed);
|
||||
controlledEnt->delegate_stufftext.Remove(delegateHandle_stufftext);
|
||||
}
|
||||
}
|
||||
|
||||
BotMovement& BotController::GetMovement()
|
||||
{
|
||||
return movement;
|
||||
|
@ -1051,7 +1060,7 @@ void BotController::Think()
|
|||
G_ClientThink(controlledEnt->edict, &ucmd, &eyeinfo);
|
||||
}
|
||||
|
||||
void BotController::Killed(Event *ev)
|
||||
void BotController::Killed(const Event& ev)
|
||||
{
|
||||
Entity *attacker;
|
||||
|
||||
|
@ -1068,7 +1077,7 @@ void BotController::Killed(Event *ev)
|
|||
m_botEyes.angles[0] = 0;
|
||||
m_botEyes.angles[1] = 0;
|
||||
|
||||
attacker = ev->GetEntity(1);
|
||||
attacker = ev.GetEntity(1);
|
||||
|
||||
if (attacker && rand() % 5 == 0) {
|
||||
// 1/5 chance to go back to the attacker position
|
||||
|
@ -1093,7 +1102,7 @@ void BotController::Killed(Event *ev)
|
|||
G_ClientUserinfoChanged(controlledEnt->edict, controlledEnt->client->pers.userinfo);
|
||||
}
|
||||
|
||||
void BotController::GotKill(Event *ev)
|
||||
void BotController::GotKill(const Event& ev)
|
||||
{
|
||||
ClearEnemy();
|
||||
m_iCuriousTime = 0;
|
||||
|
@ -1118,9 +1127,9 @@ void BotController::GotKill(Event *ev)
|
|||
}
|
||||
}
|
||||
|
||||
void BotController::EventStuffText(Event *ev)
|
||||
void BotController::EventStuffText(const str& text)
|
||||
{
|
||||
SendCommand(ev->GetString(1));
|
||||
SendCommand(text);
|
||||
}
|
||||
|
||||
void BotController::setControlledEntity(Player *player)
|
||||
|
@ -1128,6 +1137,10 @@ void BotController::setControlledEntity(Player *player)
|
|||
controlledEnt = player;
|
||||
movement.SetControlledEntity(player);
|
||||
rotation.SetControlledEntity(player);
|
||||
|
||||
delegateHandle_gotKill = player->delegate_gotKill.Add(std::bind(&BotController::GotKill, this, std::placeholders::_1));
|
||||
delegateHandle_killed = player->delegate_killed.Add(std::bind(&BotController::Killed, this, std::placeholders::_1));
|
||||
delegateHandle_stufftext = player->delegate_stufftext.Add(std::bind(&BotController::EventStuffText, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
Player *BotController::getControlledEntity() const
|
||||
|
@ -1216,42 +1229,3 @@ void BotControllerManager::ThinkControllers()
|
|||
controller->Think();
|
||||
}
|
||||
}
|
||||
|
||||
CLASS_DECLARATION(Player, PlayerBot, NULL) {
|
||||
{&EV_Killed, &PlayerBot::Killed },
|
||||
{&EV_GotKill, &PlayerBot::GotKill },
|
||||
{&EV_Player_StuffText, &PlayerBot::EventStuffText},
|
||||
{NULL, NULL }
|
||||
};
|
||||
|
||||
PlayerBot::PlayerBot()
|
||||
{
|
||||
entflags |= ECF_BOT;
|
||||
controller = NULL;
|
||||
}
|
||||
|
||||
void PlayerBot::setController(BotController *controlledBy)
|
||||
{
|
||||
controller = controlledBy;
|
||||
}
|
||||
|
||||
void PlayerBot::Spawned(void)
|
||||
{
|
||||
controller->Spawned();
|
||||
|
||||
Player::Spawned();
|
||||
}
|
||||
|
||||
void PlayerBot::Killed(Event *ev)
|
||||
{
|
||||
Player::Killed(ev);
|
||||
|
||||
controller->Killed(ev);
|
||||
}
|
||||
|
||||
void PlayerBot::GotKill(Event *ev)
|
||||
{
|
||||
Player::GotKill(ev);
|
||||
|
||||
controller->GotKill(ev);
|
||||
}
|
||||
|
|
|
@ -160,6 +160,11 @@ private:
|
|||
// Taunts
|
||||
int m_iNextTauntTime;
|
||||
|
||||
private:
|
||||
DelegateHandle delegateHandle_gotKill;
|
||||
DelegateHandle delegateHandle_killed;
|
||||
DelegateHandle delegateHandle_stufftext;
|
||||
|
||||
private:
|
||||
Weapon* FindWeaponWithAmmo(void);
|
||||
Weapon* FindMeleeWeapon(void);
|
||||
|
@ -209,6 +214,7 @@ public:
|
|||
CLASS_PROTOTYPE(BotController);
|
||||
|
||||
BotController();
|
||||
~BotController();
|
||||
|
||||
static void Init(void);
|
||||
|
||||
|
@ -229,9 +235,9 @@ public:
|
|||
|
||||
void Spawned(void);
|
||||
|
||||
void Killed(Event *ev);
|
||||
void GotKill(Event *ev);
|
||||
void EventStuffText(Event *ev);
|
||||
void Killed(const Event& ev);
|
||||
void GotKill(const Event& ev);
|
||||
void EventStuffText(const str& text);
|
||||
|
||||
BotMovement& GetMovement();
|
||||
|
||||
|
@ -282,22 +288,3 @@ private:
|
|||
};
|
||||
|
||||
extern BotManager botManager;
|
||||
|
||||
class PlayerBot : public Player
|
||||
{
|
||||
public:
|
||||
CLASS_PROTOTYPE(PlayerBot);
|
||||
|
||||
public:
|
||||
PlayerBot();
|
||||
|
||||
void setController(BotController *controlledBy);
|
||||
|
||||
void Spawned(void) override;
|
||||
|
||||
void Killed(Event *ev) override;
|
||||
void GotKill(Event *ev);
|
||||
|
||||
private:
|
||||
BotController *controller;
|
||||
};
|
||||
|
|
171
code/fgame/scriptdelegate.cpp
Normal file
171
code/fgame/scriptdelegate.cpp
Normal file
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2025 the OpenMoHAA team
|
||||
|
||||
This file is part of OpenMoHAA source code.
|
||||
|
||||
OpenMoHAA source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
OpenMoHAA source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenMoHAA source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "scriptdelegate.h"
|
||||
#include "../script/scriptexception.h"
|
||||
|
||||
ScriptDelegate *ScriptDelegate::root = NULL;
|
||||
|
||||
ScriptRegisteredDelegate_Script::ScriptRegisteredDelegate_Script(const ScriptThreadLabel& inLabel)
|
||||
: label(inLabel)
|
||||
{}
|
||||
|
||||
void ScriptRegisteredDelegate_Script::Execute(const Event& ev)
|
||||
{
|
||||
Event newev = ev;
|
||||
|
||||
label.Execute(NULL, newev);
|
||||
}
|
||||
|
||||
bool ScriptRegisteredDelegate_Script::operator==(const ScriptRegisteredDelegate_Script& registeredDelegate) const
|
||||
{
|
||||
return label == registeredDelegate.label;
|
||||
}
|
||||
|
||||
ScriptRegisteredDelegate_CodeMember::ScriptRegisteredDelegate_CodeMember(
|
||||
Class *inObject, DelegateClassResponse inResponse
|
||||
)
|
||||
: object(inObject)
|
||||
, response(inResponse)
|
||||
{}
|
||||
|
||||
void ScriptRegisteredDelegate_CodeMember::Execute(const Event& ev)
|
||||
{
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
|
||||
(object->*response)(ev);
|
||||
}
|
||||
|
||||
bool ScriptRegisteredDelegate_CodeMember::operator==(const ScriptRegisteredDelegate_CodeMember& registeredDelegate
|
||||
) const
|
||||
{
|
||||
return object == registeredDelegate.object && response == registeredDelegate.response;
|
||||
}
|
||||
|
||||
ScriptRegisteredDelegate_Code::ScriptRegisteredDelegate_Code(DelegateResponse inResponse)
|
||||
: response(inResponse)
|
||||
{}
|
||||
|
||||
void ScriptRegisteredDelegate_Code::Execute(const Event& ev)
|
||||
{
|
||||
(*response)(ev);
|
||||
}
|
||||
|
||||
bool ScriptRegisteredDelegate_Code::operator==(const ScriptRegisteredDelegate_Code& registeredDelegate) const
|
||||
{
|
||||
return response == registeredDelegate.response;
|
||||
}
|
||||
|
||||
ScriptDelegate::ScriptDelegate(const char *inName, const char *inDescription)
|
||||
: name(inName)
|
||||
, description(inDescription)
|
||||
{
|
||||
LL_SafeAddFirst(root, this, next, prev);
|
||||
}
|
||||
|
||||
ScriptDelegate::~ScriptDelegate()
|
||||
{
|
||||
LL_SafeRemoveRoot(root, this, next, prev);
|
||||
}
|
||||
|
||||
const ScriptDelegate *ScriptDelegate::GetRoot()
|
||||
{
|
||||
return root;
|
||||
}
|
||||
|
||||
const ScriptDelegate *ScriptDelegate::GetNext() const
|
||||
{
|
||||
return next;
|
||||
}
|
||||
|
||||
void ScriptDelegate::Register(const ScriptThreadLabel& label)
|
||||
{
|
||||
if (!label.IsSet()) {
|
||||
ScriptError("Invalid label specified for the script delegate");
|
||||
}
|
||||
|
||||
list_script.AddUniqueObject(label);
|
||||
}
|
||||
|
||||
void ScriptDelegate::Unregister(const ScriptThreadLabel& label)
|
||||
{
|
||||
list_script.RemoveObject(label);
|
||||
}
|
||||
|
||||
void ScriptDelegate::Register(ScriptRegisteredDelegate_Code::DelegateResponse response)
|
||||
{
|
||||
list_code.AddUniqueObject(ScriptRegisteredDelegate_Code(response));
|
||||
}
|
||||
|
||||
void ScriptDelegate::Unregister(ScriptRegisteredDelegate_Code::DelegateResponse response)
|
||||
{
|
||||
list_code.RemoveObject(response);
|
||||
}
|
||||
|
||||
void ScriptDelegate::Register(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response)
|
||||
{
|
||||
list_codeMember.AddUniqueObject(ScriptRegisteredDelegate_CodeMember(object, response));
|
||||
}
|
||||
|
||||
void ScriptDelegate::Unregister(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response)
|
||||
{
|
||||
list_codeMember.RemoveObject(ScriptRegisteredDelegate_CodeMember(object, response));
|
||||
}
|
||||
|
||||
void ScriptDelegate::Trigger(const Event& ev) const
|
||||
{
|
||||
size_t i;
|
||||
|
||||
{
|
||||
const Container<ScriptRegisteredDelegate_Script> tmpList = list_script;
|
||||
for (i = 1; i <= tmpList.NumObjects(); i++) {
|
||||
tmpList.ObjectAt(i).Execute(ev);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const Container<ScriptRegisteredDelegate_Code> tmpList = list_code;
|
||||
for (i = 1; i <= tmpList.NumObjects(); i++) {
|
||||
tmpList.ObjectAt(i).Execute(ev);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const Container<ScriptRegisteredDelegate_CodeMember> tmpList = list_codeMember;
|
||||
for (i = 1; i <= tmpList.NumObjects(); i++) {
|
||||
tmpList.ObjectAt(i).Execute(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ScriptDelegate *ScriptDelegate::GetScriptDelegate(const char *name)
|
||||
{
|
||||
for (ScriptDelegate *delegate = root; delegate; delegate = delegate->next) {
|
||||
if (!Q_stricmp(delegate->name, name)) {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
183
code/fgame/scriptdelegate.h
Normal file
183
code/fgame/scriptdelegate.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2025 the OpenMoHAA team
|
||||
|
||||
This file is part of OpenMoHAA source code.
|
||||
|
||||
OpenMoHAA source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
OpenMoHAA source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenMoHAA source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// scriptdelegate -- manages function delegate
|
||||
|
||||
#include "../qcommon/listener.h"
|
||||
#include "../qcommon/delegate.h"
|
||||
#include "gamescript.h"
|
||||
|
||||
class ScriptRegisteredDelegate
|
||||
{
|
||||
public:
|
||||
void Execute(const Event& ev);
|
||||
};
|
||||
|
||||
/**
|
||||
* Registered delegate, for scripts.
|
||||
* It contains a ScriptThreadLabel with the game script and the label to execute.
|
||||
*/
|
||||
class ScriptRegisteredDelegate_Script : public ScriptRegisteredDelegate
|
||||
{
|
||||
public:
|
||||
ScriptRegisteredDelegate_Script(const ScriptThreadLabel& inLabel);
|
||||
|
||||
void Execute(const Event& ev);
|
||||
|
||||
bool operator==(const ScriptRegisteredDelegate_Script& registeredDelegate) const;
|
||||
|
||||
private:
|
||||
ScriptThreadLabel label;
|
||||
};
|
||||
|
||||
/**
|
||||
* Registered delegate, for code use.
|
||||
* It contains the function to execute.
|
||||
*/
|
||||
class ScriptRegisteredDelegate_Code : public ScriptRegisteredDelegate
|
||||
{
|
||||
public:
|
||||
using DelegateResponse = void (*)(const Event& ev);
|
||||
|
||||
public:
|
||||
ScriptRegisteredDelegate_Code(DelegateResponse inResponse);
|
||||
|
||||
void Execute(const Event& ev);
|
||||
|
||||
bool operator==(const ScriptRegisteredDelegate_Code& registeredDelegate) const;
|
||||
|
||||
private:
|
||||
DelegateResponse response;
|
||||
};
|
||||
|
||||
/**
|
||||
* Registered delegate, for code use.
|
||||
* It contains the object along the member function to execute.
|
||||
* The function will not be executed if the object is NULL.
|
||||
*/
|
||||
class ScriptRegisteredDelegate_CodeMember : public ScriptRegisteredDelegate
|
||||
{
|
||||
public:
|
||||
using DelegateClassResponse = void (Class::*)(const Event& ev);
|
||||
|
||||
public:
|
||||
ScriptRegisteredDelegate_CodeMember(Class *inObject, DelegateClassResponse inResponse);
|
||||
|
||||
void Execute(const Event& ev);
|
||||
|
||||
bool operator==(const ScriptRegisteredDelegate_CodeMember& registeredDelegate) const;
|
||||
|
||||
private:
|
||||
SafePtr<Class> object;
|
||||
DelegateClassResponse response;
|
||||
};
|
||||
|
||||
/**
|
||||
* A script delegate provides a way for code to subscribe for events.
|
||||
* Scripts and code can register for a delegate and have their function executed
|
||||
* when the delegate gets triggered.
|
||||
*/
|
||||
class ScriptDelegate
|
||||
{
|
||||
public:
|
||||
ScriptDelegate(const char *name, const char *description);
|
||||
~ScriptDelegate();
|
||||
|
||||
static const ScriptDelegate *GetRoot();
|
||||
const ScriptDelegate *GetNext() const;
|
||||
|
||||
/**
|
||||
* Register a script label.
|
||||
*
|
||||
* @param label The label to be executed
|
||||
*/
|
||||
void Register(const ScriptThreadLabel& label);
|
||||
|
||||
/**
|
||||
* Unregistered the label.
|
||||
*
|
||||
* @param label The label to unregister
|
||||
*/
|
||||
void Unregister(const ScriptThreadLabel& label);
|
||||
|
||||
/**
|
||||
* Register a function.
|
||||
*
|
||||
* @param response The function to be executed
|
||||
*/
|
||||
void Register(ScriptRegisteredDelegate_Code::DelegateResponse response);
|
||||
|
||||
/**
|
||||
* Unregistered the function.
|
||||
*
|
||||
* @param response the function to unregister
|
||||
*/
|
||||
void Unregister(ScriptRegisteredDelegate_Code::DelegateResponse response);
|
||||
|
||||
/**
|
||||
* Register with an object and a member function.
|
||||
*
|
||||
* @param object The object to notify
|
||||
* @param response The member function of the object to be executed
|
||||
*/
|
||||
void Register(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response);
|
||||
|
||||
/**
|
||||
* Unregistered the member function.
|
||||
*
|
||||
* @param object The object where the member function is
|
||||
* @param response The member function to unregister
|
||||
*/
|
||||
void Unregister(Class *object, ScriptRegisteredDelegate_CodeMember::DelegateClassResponse response);
|
||||
|
||||
/**
|
||||
* Executes all registered delegates with the specified event.
|
||||
*
|
||||
* @param ev Parameter list
|
||||
*/
|
||||
void Trigger(const Event& ev) const;
|
||||
|
||||
/**
|
||||
* Search and return the specified script delegate by name.
|
||||
*
|
||||
* @param name The name to search for
|
||||
*/
|
||||
static ScriptDelegate *GetScriptDelegate(const char *name);
|
||||
|
||||
// non-movable and non-copyable
|
||||
ScriptDelegate(ScriptDelegate&& other) = delete;
|
||||
ScriptDelegate& operator=(ScriptDelegate&& other) = delete;
|
||||
ScriptDelegate(const ScriptDelegate& other) = delete;
|
||||
ScriptDelegate& operator=(const ScriptDelegate& other) = delete;
|
||||
|
||||
private:
|
||||
// Linked-list
|
||||
ScriptDelegate *next;
|
||||
ScriptDelegate *prev;
|
||||
static ScriptDelegate *root;
|
||||
const char *name;
|
||||
const char *description;
|
||||
|
||||
Container<ScriptRegisteredDelegate_Script> list_script;
|
||||
Container<ScriptRegisteredDelegate_Code> list_code;
|
||||
Container<ScriptRegisteredDelegate_CodeMember> list_codeMember;
|
||||
};
|
|
@ -1676,6 +1676,24 @@ Event EV_ScriptThread_UnregisterEv
|
|||
"Unregisters script callback handler for specified event",
|
||||
EV_RETURN
|
||||
);
|
||||
Event EV_ScriptThread_Event_Subscribe
|
||||
(
|
||||
"event_subscribe",
|
||||
EV_DEFAULT,
|
||||
"ss",
|
||||
"eventname script",
|
||||
"Subscribe to the specified event. The specified script will be executed when the event gets triggered.",
|
||||
EV_NORMAL
|
||||
);
|
||||
Event EV_ScriptThread_Event_Unsubscribe
|
||||
(
|
||||
"event_unsubscribe",
|
||||
EV_DEFAULT,
|
||||
"ss",
|
||||
"eventname script",
|
||||
"Unsubscribe the script from the specified event.",
|
||||
EV_NORMAL
|
||||
);
|
||||
Event EV_ScriptThread_Conprintf
|
||||
(
|
||||
"conprintf",
|
||||
|
@ -2193,6 +2211,8 @@ CLASS_DECLARATION(Listener, ScriptThread, NULL) {
|
|||
{&EV_ScriptThread_TypeOf, &ScriptThread::TypeOfVariable },
|
||||
{&EV_ScriptThread_RegisterEv, &ScriptThread::RegisterEvent },
|
||||
{&EV_ScriptThread_UnregisterEv, &ScriptThread::UnregisterEvent },
|
||||
{&EV_ScriptThread_Event_Subscribe, &ScriptThread::SubscribeEvent },
|
||||
{&EV_ScriptThread_Event_Unsubscribe, &ScriptThread::UnsubscribeEvent },
|
||||
{&EV_ScriptThread_CancelWaiting, &ScriptThread::CancelWaiting },
|
||||
{&EV_ScriptThread_GetTime, &ScriptThread::GetTime },
|
||||
{&EV_ScriptThread_GetTimeZone, &ScriptThread::GetTimeZone },
|
||||
|
@ -6855,6 +6875,8 @@ void ScriptThread::RegisterEvent(Event *ev)
|
|||
char eventname_full[64];
|
||||
scriptedEvType_t evType;
|
||||
|
||||
ScriptDeprecatedAltMethod("event_subscribe");
|
||||
|
||||
eventname = ev->GetString(1);
|
||||
|
||||
evType = EventNameToType(eventname, eventname_full);
|
||||
|
@ -6886,6 +6908,8 @@ void ScriptThread::UnregisterEvent(Event *ev)
|
|||
int numArgs = 0;
|
||||
scriptedEvType_t evType;
|
||||
|
||||
ScriptDeprecatedAltMethod("event_unsubscribe");
|
||||
|
||||
eventname = ev->GetString(1);
|
||||
|
||||
evType = EventNameToType(eventname, NULL);
|
||||
|
@ -6919,6 +6943,42 @@ void ScriptThread::UnregisterEvent(Event *ev)
|
|||
ev->AddInteger(0);
|
||||
}
|
||||
|
||||
void ScriptThread::SubscribeEvent(Event *ev)
|
||||
{
|
||||
str eventName;
|
||||
ScriptDelegate *delegate;
|
||||
ScriptThreadLabel label;
|
||||
|
||||
eventName = ev->GetString(1);
|
||||
|
||||
delegate = ScriptDelegate::GetScriptDelegate(eventName);
|
||||
if (!delegate) {
|
||||
throw ScriptException("Invalid event '%s'", eventName.c_str());
|
||||
}
|
||||
|
||||
label.SetThread(ev->GetValue(2));
|
||||
|
||||
delegate->Register(label);
|
||||
}
|
||||
|
||||
void ScriptThread::UnsubscribeEvent(Event *ev)
|
||||
{
|
||||
str eventName;
|
||||
ScriptDelegate* delegate;
|
||||
ScriptThreadLabel label;
|
||||
|
||||
eventName = ev->GetString(1);
|
||||
|
||||
delegate = ScriptDelegate::GetScriptDelegate(eventName);
|
||||
if (!delegate) {
|
||||
throw ScriptException("Invalid event '%s'", eventName.c_str());
|
||||
}
|
||||
|
||||
label.SetThread(ev->GetValue(2));
|
||||
|
||||
delegate->Unregister(label);
|
||||
}
|
||||
|
||||
void ScriptThread::TypeOfVariable(Event *ev)
|
||||
{
|
||||
int numArgs = 0;
|
||||
|
|
|
@ -345,6 +345,9 @@ public:
|
|||
void UnregisterEvent(Event *ev);
|
||||
void VisionGetNaked(Event *ev);
|
||||
void VisionSetNaked(Event *ev);
|
||||
|
||||
void SubscribeEvent(Event *ev);
|
||||
void UnsubscribeEvent(Event *ev);
|
||||
};
|
||||
|
||||
class OSFile : public Listener
|
||||
|
|
|
@ -1368,7 +1368,7 @@ void Sentient::ArmorDamage(Event *ev)
|
|||
Vector position;
|
||||
Vector normal;
|
||||
Vector direction;
|
||||
Event *event;
|
||||
Event event;
|
||||
int dflags;
|
||||
int meansofdeath;
|
||||
int knockback;
|
||||
|
@ -1582,50 +1582,56 @@ void Sentient::ArmorDamage(Event *ev)
|
|||
health = 0;
|
||||
|
||||
if (attacker) {
|
||||
// Added in OPM
|
||||
event = new Event(EV_GotKill);
|
||||
event->AddEntity(this);
|
||||
event->AddInteger(damage);
|
||||
event->AddEntity(inflictor);
|
||||
event->AddInteger(meansofdeath);
|
||||
event->AddInteger(0);
|
||||
const EntityPtr attackerPtr = attacker;
|
||||
|
||||
attacker->ProcessEvent(event);
|
||||
// Added in OPM
|
||||
event = Event(EV_GotKill);
|
||||
event.AddEntity(this);
|
||||
event.AddInteger(damage);
|
||||
event.AddEntity(inflictor);
|
||||
event.AddInteger(meansofdeath);
|
||||
event.AddInteger(0);
|
||||
|
||||
attackerPtr->ProcessEvent(event);
|
||||
if (attackerPtr) {
|
||||
attackerPtr->delegate_gotKill.Execute(event);
|
||||
}
|
||||
}
|
||||
|
||||
event = new Event(EV_Killed, 10);
|
||||
event->AddEntity(attacker);
|
||||
event->AddFloat(damage);
|
||||
event->AddEntity(inflictor);
|
||||
event->AddVector(position);
|
||||
event->AddVector(direction);
|
||||
event->AddVector(normal);
|
||||
event->AddInteger(knockback);
|
||||
event->AddInteger(dflags);
|
||||
event->AddInteger(meansofdeath);
|
||||
event->AddInteger(location);
|
||||
event = Event(EV_Killed, 10);
|
||||
event.AddEntity(attacker);
|
||||
event.AddFloat(damage);
|
||||
event.AddEntity(inflictor);
|
||||
event.AddVector(position);
|
||||
event.AddVector(direction);
|
||||
event.AddVector(normal);
|
||||
event.AddInteger(knockback);
|
||||
event.AddInteger(dflags);
|
||||
event.AddInteger(meansofdeath);
|
||||
event.AddInteger(location);
|
||||
|
||||
ProcessEvent(event);
|
||||
delegate_killed.Execute(event);
|
||||
}
|
||||
|
||||
if (health > 0) {
|
||||
// Send pain event
|
||||
event = new Event(EV_Pain, 10);
|
||||
event->AddEntity(attacker);
|
||||
event->AddFloat(damage);
|
||||
event->AddEntity(inflictor);
|
||||
event->AddVector(position);
|
||||
event->AddVector(direction);
|
||||
event->AddVector(normal);
|
||||
event->AddInteger(knockback);
|
||||
event->AddInteger(dflags);
|
||||
event->AddInteger(meansofdeath);
|
||||
event->AddInteger(location);
|
||||
event = Event(EV_Pain, 10);
|
||||
event.AddEntity(attacker);
|
||||
event.AddFloat(damage);
|
||||
event.AddEntity(inflictor);
|
||||
event.AddVector(position);
|
||||
event.AddVector(direction);
|
||||
event.AddVector(normal);
|
||||
event.AddInteger(knockback);
|
||||
event.AddInteger(dflags);
|
||||
event.AddInteger(meansofdeath);
|
||||
event.AddInteger(location);
|
||||
|
||||
ProcessEvent(event);
|
||||
}
|
||||
|
||||
return;
|
||||
delegate_damage.Execute(*ev);
|
||||
}
|
||||
|
||||
qboolean Sentient::CanBlock(int meansofdeath, qboolean full_block)
|
||||
|
|
|
@ -356,11 +356,6 @@ int SimpleEntity::IsSubclassOfCrateObject(void) const
|
|||
return (entflags & ECF_CRATEOBJECT);
|
||||
}
|
||||
|
||||
int SimpleEntity::IsSubclassOfBot(void) const
|
||||
{
|
||||
return (entflags & ECF_BOT);
|
||||
}
|
||||
|
||||
void SimpleEntity::SetTargetName(str targetname)
|
||||
{
|
||||
if (!world) {
|
||||
|
|
|
@ -91,7 +91,6 @@ public:
|
|||
int IsSubclassOfVehiclePoint(void) const;
|
||||
int IsSubclassOfSplinePath(void) const;
|
||||
int IsSubclassOfCrateObject(void) const;
|
||||
int IsSubclassOfBot(void) const;
|
||||
|
||||
void GetOrigin(Event *ev);
|
||||
void SetOrigin(Event *ev);
|
||||
|
|
|
@ -13,6 +13,7 @@ set(SOURCES_SHARED_UBER
|
|||
"${CMAKE_SOURCE_DIR}/code/qcommon/class.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/code/qcommon/con_set.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/code/qcommon/con_timer.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/code/qcommon/delegate.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/code/qcommon/lightclass.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/code/qcommon/listener.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/code/qcommon/lz77.cpp"
|
||||
|
|
52
code/qcommon/delegate.cpp
Normal file
52
code/qcommon/delegate.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2025 the OpenMoHAA team
|
||||
|
||||
This file is part of OpenMoHAA source code.
|
||||
|
||||
OpenMoHAA source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
OpenMoHAA source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenMoHAA source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#include "delegate.h"
|
||||
|
||||
uint64_t DelegateHandle::currentHandle = 0;
|
||||
|
||||
DelegateHandle::DelegateHandle()
|
||||
: handle(GenerateDelegateID())
|
||||
{}
|
||||
|
||||
bool DelegateHandle::operator==(const DelegateHandle& other) const
|
||||
{
|
||||
return handle == other.handle;
|
||||
}
|
||||
|
||||
bool DelegateHandle::operator!=(const DelegateHandle& other) const
|
||||
{
|
||||
return handle != other.handle;
|
||||
}
|
||||
|
||||
uint64_t DelegateHandle::GenerateDelegateID()
|
||||
{
|
||||
uint64_t handle;
|
||||
|
||||
handle = ++currentHandle;
|
||||
|
||||
if (handle == 0) {
|
||||
handle = ++currentHandle;
|
||||
}
|
||||
|
||||
return handle;
|
||||
}
|
127
code/qcommon/delegate.h
Normal file
127
code/qcommon/delegate.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
===========================================================================
|
||||
Copyright (C) 2025 the OpenMoHAA team
|
||||
|
||||
This file is part of OpenMoHAA source code.
|
||||
|
||||
OpenMoHAA source code is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the License,
|
||||
or (at your option) any later version.
|
||||
|
||||
OpenMoHAA source code is distributed in the hope that it will be
|
||||
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenMoHAA source code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "container.h"
|
||||
|
||||
template<typename T>
|
||||
using Delegate = std::function<T>;
|
||||
|
||||
struct DelegateHandle {
|
||||
public:
|
||||
DelegateHandle();
|
||||
|
||||
bool operator==(const DelegateHandle& other) const;
|
||||
bool operator!=(const DelegateHandle& other) const;
|
||||
|
||||
private:
|
||||
static uint64_t GenerateDelegateID();
|
||||
static uint64_t currentHandle;
|
||||
|
||||
uint64_t handle;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class DelegateMultiElement
|
||||
{
|
||||
public:
|
||||
DelegateMultiElement(Delegate<T>&& inFunction);
|
||||
|
||||
template<typename... Args>
|
||||
void Execute(Args&&...args) const;
|
||||
|
||||
DelegateHandle GetHandle() const;
|
||||
|
||||
private:
|
||||
DelegateHandle handle;
|
||||
Delegate<T> func;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
DelegateMultiElement<T>::DelegateMultiElement(Delegate<T>&& inFunction)
|
||||
: func(inFunction)
|
||||
{}
|
||||
|
||||
template<typename T>
|
||||
template<typename... Args>
|
||||
void DelegateMultiElement<T>::Execute(Args&&...args) const
|
||||
{
|
||||
func(std::move(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
DelegateHandle DelegateMultiElement<T>::GetHandle() const
|
||||
{
|
||||
return handle;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class MulticastDelegate
|
||||
{
|
||||
public:
|
||||
DelegateHandle Add(Delegate<T>&& function);
|
||||
void Remove(DelegateHandle handle);
|
||||
|
||||
template<typename... Args>
|
||||
void Execute(Args&&...args);
|
||||
|
||||
private:
|
||||
Container<DelegateMultiElement<T>> delegates;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
DelegateHandle MulticastDelegate<T>::Add(Delegate<T>&& function)
|
||||
{
|
||||
int index = delegates.AddObject(DelegateMultiElement<T>(std::move(function)));
|
||||
|
||||
return delegates.ObjectAt(index).GetHandle();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MulticastDelegate<T>::Remove(DelegateHandle handle)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = delegates.NumObjects(); i > 0; i--) {
|
||||
const DelegateMultiElement<T>& elem = delegates.ObjectAt(i);
|
||||
|
||||
if (elem.GetHandle() == handle) {
|
||||
delegates.RemoveObjectAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename... Args>
|
||||
void MulticastDelegate<T>::Execute(Args&&...args)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 1; i <= delegates.NumObjects(); i++) {
|
||||
const DelegateMultiElement<T>& element = delegates.ObjectAt(i);
|
||||
|
||||
element.Execute(std::move(args)...);
|
||||
}
|
||||
}
|
|
@ -1711,7 +1711,7 @@ Event::Event(const Event& ev)
|
|||
maxDataSize = ev.maxDataSize;
|
||||
|
||||
if (dataSize) {
|
||||
data = new ScriptVariable[dataSize];
|
||||
data = new ScriptVariable[maxDataSize];
|
||||
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
data[i] = ev.data[i];
|
||||
|
@ -1733,7 +1733,7 @@ Event::Event(const Event& ev, int numArgs)
|
|||
maxDataSize = ev.maxDataSize;
|
||||
|
||||
if (dataSize) {
|
||||
data = new ScriptVariable[dataSize];
|
||||
data = new ScriptVariable[maxDataSize];
|
||||
|
||||
for (int i = 0; i < dataSize; i++) {
|
||||
data[i] = ev.data[i];
|
||||
|
@ -2117,7 +2117,7 @@ void Event::Clear(void)
|
|||
CheckPos
|
||||
=======================
|
||||
*/
|
||||
void Event::CheckPos(int pos)
|
||||
void Event::CheckPos(int pos) const
|
||||
{
|
||||
if (pos > NumArgs()) {
|
||||
ScriptError("Index %d out of range.", pos);
|
||||
|
@ -2129,7 +2129,7 @@ void Event::CheckPos(int pos)
|
|||
GetBoolean
|
||||
=======================
|
||||
*/
|
||||
bool Event::GetBoolean(int pos)
|
||||
bool Event::GetBoolean(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2143,7 +2143,7 @@ bool Event::GetBoolean(int pos)
|
|||
GetConstString
|
||||
=======================
|
||||
*/
|
||||
const_str Event::GetConstString(int pos)
|
||||
const_str Event::GetConstString(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2157,7 +2157,7 @@ const_str Event::GetConstString(int pos)
|
|||
GetEntity
|
||||
=======================
|
||||
*/
|
||||
Entity *Event::GetEntity(int pos)
|
||||
Entity *Event::GetEntity(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2169,7 +2169,7 @@ Entity *Event::GetEntity(int pos)
|
|||
GetFloat
|
||||
=======================
|
||||
*/
|
||||
float Event::GetFloat(int pos)
|
||||
float Event::GetFloat(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2181,7 +2181,7 @@ float Event::GetFloat(int pos)
|
|||
GetInteger
|
||||
=======================
|
||||
*/
|
||||
int Event::GetInteger(int pos)
|
||||
int Event::GetInteger(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2193,7 +2193,7 @@ int Event::GetInteger(int pos)
|
|||
GetListener
|
||||
=======================
|
||||
*/
|
||||
Listener *Event::GetListener(int pos)
|
||||
Listener *Event::GetListener(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2207,7 +2207,7 @@ Listener *Event::GetListener(int pos)
|
|||
GetSimpleEntity
|
||||
=======================
|
||||
*/
|
||||
SimpleEntity *Event::GetSimpleEntity(int pos)
|
||||
SimpleEntity *Event::GetSimpleEntity(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2221,7 +2221,7 @@ SimpleEntity *Event::GetSimpleEntity(int pos)
|
|||
GetString
|
||||
=======================
|
||||
*/
|
||||
str Event::GetString(int pos)
|
||||
str Event::GetString(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
return variable.stringValue();
|
||||
|
@ -2232,7 +2232,7 @@ str Event::GetString(int pos)
|
|||
GetToken
|
||||
=======================
|
||||
*/
|
||||
str Event::GetToken(int pos)
|
||||
str Event::GetToken(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
return variable.stringValue();
|
||||
|
@ -2243,7 +2243,7 @@ str Event::GetToken(int pos)
|
|||
GetValue
|
||||
=======================
|
||||
*/
|
||||
ScriptVariable& Event::GetValue(int pos)
|
||||
ScriptVariable& Event::GetValue(int pos) const
|
||||
{
|
||||
if (pos < 0) {
|
||||
pos = NumArgs() + pos + 1;
|
||||
|
@ -2303,7 +2303,7 @@ ScriptVariable& Event::GetValue(void)
|
|||
GetVector
|
||||
=======================
|
||||
*/
|
||||
Vector Event::GetVector(int pos)
|
||||
Vector Event::GetVector(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2317,7 +2317,7 @@ Vector Event::GetVector(int pos)
|
|||
GetPathNode
|
||||
=======================
|
||||
*/
|
||||
PathNode *Event::GetPathNode(int pos)
|
||||
PathNode *Event::GetPathNode(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2329,7 +2329,7 @@ PathNode *Event::GetPathNode(int pos)
|
|||
GetWaypoint
|
||||
=======================
|
||||
*/
|
||||
Waypoint *Event::GetWaypoint(int pos)
|
||||
Waypoint *Event::GetWaypoint(int pos) const
|
||||
{
|
||||
ScriptVariable& variable = GetValue(pos);
|
||||
|
||||
|
@ -2343,7 +2343,7 @@ Waypoint *Event::GetWaypoint(int pos)
|
|||
IsEntityAt
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsEntityAt(int pos)
|
||||
qboolean Event::IsEntityAt(int pos) const
|
||||
{
|
||||
CheckPos(pos);
|
||||
|
||||
|
@ -2355,7 +2355,7 @@ qboolean Event::IsEntityAt(int pos)
|
|||
IsListenerAt
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsListenerAt(int pos)
|
||||
qboolean Event::IsListenerAt(int pos) const
|
||||
{
|
||||
CheckPos(pos);
|
||||
|
||||
|
@ -2367,7 +2367,7 @@ qboolean Event::IsListenerAt(int pos)
|
|||
IsNilAt
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsNilAt(int pos)
|
||||
qboolean Event::IsNilAt(int pos) const
|
||||
{
|
||||
CheckPos(pos);
|
||||
|
||||
|
@ -2379,7 +2379,7 @@ qboolean Event::IsNilAt(int pos)
|
|||
IsNumericAt
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsNumericAt(int pos)
|
||||
qboolean Event::IsNumericAt(int pos) const
|
||||
{
|
||||
CheckPos(pos);
|
||||
|
||||
|
@ -2393,7 +2393,7 @@ qboolean Event::IsNumericAt(int pos)
|
|||
IsSimpleEntityAt
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsSimpleEntityAt(int pos)
|
||||
qboolean Event::IsSimpleEntityAt(int pos) const
|
||||
{
|
||||
CheckPos(pos);
|
||||
|
||||
|
@ -2407,7 +2407,7 @@ qboolean Event::IsSimpleEntityAt(int pos)
|
|||
IsStringAt
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsStringAt(int pos)
|
||||
qboolean Event::IsStringAt(int pos) const
|
||||
{
|
||||
CheckPos(pos);
|
||||
|
||||
|
@ -2419,7 +2419,7 @@ qboolean Event::IsStringAt(int pos)
|
|||
IsVectorAt
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsVectorAt(int pos)
|
||||
qboolean Event::IsVectorAt(int pos) const
|
||||
{
|
||||
CheckPos(pos);
|
||||
|
||||
|
@ -2431,7 +2431,7 @@ qboolean Event::IsVectorAt(int pos)
|
|||
IsFromScript
|
||||
=======================
|
||||
*/
|
||||
qboolean Event::IsFromScript()
|
||||
qboolean Event::IsFromScript() const
|
||||
{
|
||||
return fromScript;
|
||||
}
|
||||
|
@ -2441,7 +2441,7 @@ qboolean Event::IsFromScript()
|
|||
NumArgs
|
||||
=======================
|
||||
*/
|
||||
int Event::NumArgs()
|
||||
int Event::NumArgs() const
|
||||
{
|
||||
return dataSize;
|
||||
}
|
||||
|
|
|
@ -364,45 +364,45 @@ public:
|
|||
|
||||
void Clear(void);
|
||||
|
||||
void CheckPos(int pos);
|
||||
void CheckPos(int pos) const;
|
||||
|
||||
bool GetBoolean(int pos);
|
||||
bool GetBoolean(int pos) const;
|
||||
|
||||
const_str GetConstString(int pos);
|
||||
const_str GetConstString(int pos) const;
|
||||
|
||||
Entity *GetEntity(int pos);
|
||||
Entity *GetEntity(int pos) const;
|
||||
|
||||
float GetFloat(int pos);
|
||||
int GetInteger(int pos);
|
||||
Listener *GetListener(int pos);
|
||||
float GetFloat(int pos) const;
|
||||
int GetInteger(int pos) const;
|
||||
Listener *GetListener(int pos) const;
|
||||
|
||||
class PathNode *GetPathNode(int pos);
|
||||
class PathNode *GetPathNode(int pos) const;
|
||||
|
||||
#ifdef WITH_SCRIPT_ENGINE
|
||||
SimpleEntity *GetSimpleEntity(int pos);
|
||||
SimpleEntity *GetSimpleEntity(int pos) const;
|
||||
#endif
|
||||
|
||||
str GetString(int pos);
|
||||
str GetToken(int pos);
|
||||
ScriptVariable& GetValue(int pos);
|
||||
str GetString(int pos) const;
|
||||
str GetToken(int pos) const;
|
||||
ScriptVariable& GetValue(int pos) const;
|
||||
ScriptVariable& GetValue(void);
|
||||
Vector GetVector(int pos);
|
||||
Vector GetVector(int pos) const;
|
||||
|
||||
class Waypoint *GetWaypoint(int pos);
|
||||
class Waypoint *GetWaypoint(int pos) const;
|
||||
|
||||
qboolean IsEntityAt(int pos);
|
||||
qboolean IsListenerAt(int pos);
|
||||
qboolean IsNilAt(int pos);
|
||||
qboolean IsNumericAt(int pos);
|
||||
qboolean IsEntityAt(int pos) const;
|
||||
qboolean IsListenerAt(int pos) const;
|
||||
qboolean IsNilAt(int pos) const;
|
||||
qboolean IsNumericAt(int pos) const;
|
||||
#ifdef WITH_SCRIPT_ENGINE
|
||||
qboolean IsSimpleEntityAt(int pos);
|
||||
qboolean IsSimpleEntityAt(int pos) const;
|
||||
#endif
|
||||
qboolean IsStringAt(int pos);
|
||||
qboolean IsVectorAt(int pos);
|
||||
qboolean IsStringAt(int pos) const;
|
||||
qboolean IsVectorAt(int pos) const;
|
||||
|
||||
qboolean IsFromScript(void);
|
||||
qboolean IsFromScript(void) const;
|
||||
|
||||
int NumArgs();
|
||||
int NumArgs() const;
|
||||
};
|
||||
|
||||
#define NODE_CANCEL 1
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue