|
|
|
/**
|
|
|
|
* Simple class to simplify announcements of changes made by Futility's
|
|
|
|
* commands. Allows to announnce different messages to self, target and others;
|
|
|
|
* changing them up when self coincides with target.
|
|
|
|
* Copyright 2022 Anton Tarasenko
|
|
|
|
*------------------------------------------------------------------------------
|
|
|
|
* This file is part of Acedia.
|
|
|
|
*
|
|
|
|
* Acedia 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, version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Acedia 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 Acedia. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
class CommandAnnouncer extends AcediaObject;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* # `CommandAnnouncer`
|
|
|
|
*
|
|
|
|
* Simple class to simplify announcements of changes made by Futility's
|
|
|
|
* commands. Allows to announnce different messages to self, target and others;
|
|
|
|
* changing them up when self coincides with target.
|
|
|
|
* Technically only for reporting successes, since failures are only
|
|
|
|
* reported to the instigator and are, therefore, simple. But for the sake of
|
|
|
|
* consistency, every report can be placed here.
|
|
|
|
*
|
|
|
|
* ## Usage
|
|
|
|
*
|
|
|
|
* There is supposed to be a separate announcer class for every command class,
|
|
|
|
* so there's two steps to setting one up: creating new class and putting it
|
|
|
|
* to proper use.
|
|
|
|
*
|
|
|
|
* ### Creating new `CommandAnnouncer` class
|
|
|
|
*
|
|
|
|
* Step by step the process is:
|
|
|
|
* 1. Declare a new class, extending `CommandAnnouncer`;
|
|
|
|
* 2. Declare iinside `AnnouncementVariations` field variables for every
|
|
|
|
* announcement;
|
|
|
|
* 3. Declare a `Finalizer()` and place a `FreeVariations(...);` line for
|
|
|
|
* each announcement variable inside. Don't forget to later also make
|
|
|
|
* a `super.Finalizer();` call;
|
|
|
|
* 4. For every announcement make a separate method that accepts values to
|
|
|
|
* be included in that announcement as arguments.
|
|
|
|
* 5. Inside that method check whether corresponding announcement variable
|
|
|
|
* was already initialized (`initialized` field in side
|
|
|
|
* `AnnouncementVariations` struct) and otherwise initialize all
|
|
|
|
* contained `TextTemplate`s.
|
|
|
|
* 6. Fill every template with passed arguments ("instigator" and "target"
|
|
|
|
* arguments are auto-filled later). For that you can use auxiliary
|
|
|
|
* method `MakeArray()`, e.g.
|
|
|
|
* ```unrealscript
|
|
|
|
* local int i;
|
|
|
|
* local array<TextTemplate> templates;
|
|
|
|
* // ...
|
|
|
|
* templates = MakeArray(gainedDosh);
|
|
|
|
* for (i = 0; i < templates.length; i += 1) {
|
|
|
|
* templates[i].Reset().ArgInt(doshAmount);
|
|
|
|
* }
|
|
|
|
* ```
|
|
|
|
* 7. Make a `MakeAnnouncement()`, passing it `AnnouncementVariations` that
|
|
|
|
* you've just (initialized and) filled with arguments.
|
|
|
|
*
|
|
|
|
* ### Using created `CommandAnnouncer` class
|
|
|
|
*
|
|
|
|
* Simply allocate variable of that class, make a `Setup()` call inside
|
|
|
|
* `Executed()` and `ExecutedFor()` (only necessary to do in the one you are
|
|
|
|
* using).
|
|
|
|
* Since it is way more efficient to only allocate such variable once
|
|
|
|
* (avoiding creating templates every time), it is recommended that you create
|
|
|
|
* it inside `BuildData()` call and remember that instance in a field variable.
|
|
|
|
* You then simply need to declare command's finalizer to deallocate it.
|
|
|
|
* Just don't forget to call `super.Finalizer()` as well.
|
|
|
|
*/
|
|
|
|
|
|
|
|
var private EPlayer instigator, target;
|
|
|
|
var private int instigatorLifeVersion, targetLifeVersion;
|
|
|
|
var private ConsoleWriter publicConsole;
|
|
|
|
var private int publicConsoleLifeVersion;
|
|
|
|
|
|
|
|
var private MutableText instigatorName, targetName;
|
|
|
|
|
|
|
|
struct AnnouncementVariations
|
|
|
|
{
|
|
|
|
var public bool initialized;
|
|
|
|
// `toSelf...` == command's instigator is targeting himself/herself;
|
|
|
|
// `toOther...` == command's instigator is targeting somebody else;
|
|
|
|
// `...report` == message is for a report to command's instigator;
|
|
|
|
// `...private` == message is for a report to command's target;
|
|
|
|
// `...public` == message is for a report to eveyone who isn't
|
|
|
|
// an instigator or a target.
|
|
|
|
var public TextTemplate toSelfReport;
|
|
|
|
var public TextTemplate toSelfPublic;
|
|
|
|
var public TextTemplate toOtherReport;
|
|
|
|
var public TextTemplate toOtherPrivate;
|
|
|
|
var public TextTemplate toOtherPublic;
|
|
|
|
};
|
|
|
|
|
|
|
|
protected function Finalizer()
|
|
|
|
{
|
|
|
|
instigator = none;
|
|
|
|
target = none;
|
|
|
|
publicConsole = none;
|
|
|
|
_.memory.Free(instigatorName);
|
|
|
|
_.memory.Free(targetName);
|
|
|
|
instigatorName = none;
|
|
|
|
targetName = none;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepares caller `CommandAnnouncer` to make announcements about
|
|
|
|
* `newInstigator` player affecting `newTarget` player.
|
|
|
|
*
|
|
|
|
* @param newTarget Player that is targeted by the command.
|
|
|
|
* @param newInstigator Player that is calling the command, can be
|
|
|
|
* the same as `newTarget`.
|
|
|
|
* @param newPublicConsole Console instance to announce command's action to
|
|
|
|
* other (directly unaffected) players.
|
|
|
|
*/
|
|
|
|
public final function Setup(
|
|
|
|
EPlayer newTarget,
|
|
|
|
EPlayer newInstigator,
|
|
|
|
ConsoleWriter newPublicConsole)
|
|
|
|
{
|
|
|
|
target = none;
|
|
|
|
_.memory.Free(targetName);
|
|
|
|
targetName = none;
|
|
|
|
if (newTarget != none && newTarget.IsAllocated())
|
|
|
|
{
|
|
|
|
target = newTarget;
|
|
|
|
targetLifeVersion = newTarget.GetLifeVersion();
|
|
|
|
targetName = target
|
|
|
|
.GetName()
|
|
|
|
.IntoMutableText()
|
|
|
|
.ChangeDefaultColor(_.color.LightGray);
|
|
|
|
}
|
|
|
|
instigator = none;
|
|
|
|
_.memory.Free(instigatorName);
|
|
|
|
instigatorName = none;
|
|
|
|
if (newInstigator != none && newInstigator.IsAllocated())
|
|
|
|
{
|
|
|
|
instigator = newInstigator;
|
|
|
|
instigatorLifeVersion = newInstigator.GetLifeVersion();
|
|
|
|
instigatorName = instigator
|
|
|
|
.GetName()
|
|
|
|
.IntoMutableText()
|
|
|
|
.ChangeDefaultColor(_.color.LightGray);
|
|
|
|
}
|
|
|
|
publicConsole = none;
|
|
|
|
if (newPublicConsole != none && newPublicConsole.IsAllocated())
|
|
|
|
{
|
|
|
|
publicConsole = newPublicConsole;
|
|
|
|
publicConsoleLifeVersion = newPublicConsole.GetLifeVersion();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Makes appropriate announcements from `variations` to appropriate targets.
|
|
|
|
*
|
|
|
|
* @param variations Struct with announcement templates to make.
|
|
|
|
*/
|
|
|
|
protected final function MakeAnnouncement(AnnouncementVariations variations)
|
|
|
|
{
|
|
|
|
local ConsoleWriter instigatorConsole, targetConsole;
|
|
|
|
|
|
|
|
if (!variations.initialized) return;
|
|
|
|
if (!ValidateClasses()) return;
|
|
|
|
|
|
|
|
instigatorConsole = _.console.For(instigator);
|
|
|
|
targetConsole = _.console.For(target);
|
|
|
|
if (target == none || instigator.SameAs(target))
|
|
|
|
{
|
|
|
|
// If instigator is targeting himself, then there is no need for
|
|
|
|
// a separate announcement to target
|
|
|
|
AnnounceTemplate(instigatorConsole, variations.toSelfReport);
|
|
|
|
AnnounceTemplate(publicConsole, variations.toSelfPublic);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Otherwise report to three different targets
|
|
|
|
AnnounceTemplate(instigatorConsole, variations.toOtherReport);
|
|
|
|
AnnounceTemplate(targetConsole, variations.toOtherPrivate);
|
|
|
|
AnnounceTemplate(publicConsole, variations.toOtherPublic);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Auxiliary method to free all objects inside given `AnnouncementVariations`
|
|
|
|
* struct.
|
|
|
|
*
|
|
|
|
* @param variations Struct, whos contained objects methodf should free.
|
|
|
|
*/
|
|
|
|
protected final function FreeVariations(out AnnouncementVariations variations)
|
|
|
|
{
|
|
|
|
_.memory.Free(variations.toSelfReport);
|
|
|
|
_.memory.Free(variations.toSelfPublic);
|
|
|
|
_.memory.Free(variations.toOtherReport);
|
|
|
|
_.memory.Free(variations.toOtherPrivate);
|
|
|
|
_.memory.Free(variations.toOtherPublic);
|
|
|
|
variations.toSelfReport = none;
|
|
|
|
variations.toSelfPublic = none;
|
|
|
|
variations.toOtherReport = none;
|
|
|
|
variations.toOtherPrivate = none;
|
|
|
|
variations.toOtherPublic = none;
|
|
|
|
variations.initialized = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Auxiliary method to put all `TextTemplate`s inside `variations` into
|
|
|
|
* an array that can then be easily iterated over.
|
|
|
|
*/
|
|
|
|
protected final function array<TextTemplate> MakeArray(
|
|
|
|
AnnouncementVariations variations)
|
|
|
|
{
|
|
|
|
local array<TextTemplate> result;
|
|
|
|
|
|
|
|
if (variations.toSelfReport != none) {
|
|
|
|
result[result.length] = variations.toSelfReport;
|
|
|
|
}
|
|
|
|
if (variations.toSelfPublic != none) {
|
|
|
|
result[result.length] = variations.toSelfPublic;
|
|
|
|
}
|
|
|
|
if (variations.toOtherReport != none) {
|
|
|
|
result[result.length] = variations.toOtherReport;
|
|
|
|
}
|
|
|
|
if (variations.toOtherPrivate != none) {
|
|
|
|
result[result.length] = variations.toOtherPrivate;
|
|
|
|
}
|
|
|
|
if (variations.toOtherPublic != none) {
|
|
|
|
result[result.length] = variations.toOtherPublic;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
private final function bool ValidateClasses()
|
|
|
|
{
|
|
|
|
if (instigator == none) return false;
|
|
|
|
if (publicConsole == none) return false;
|
|
|
|
if (instigator.GetLifeVersion() != instigatorLifeVersion) return false;
|
|
|
|
if (!instigator.IsExistent()) return false;
|
|
|
|
|
|
|
|
if (target != none)
|
|
|
|
{
|
|
|
|
if ( target.GetLifeVersion() != targetLifeVersion
|
|
|
|
|| !target.IsExistent())
|
|
|
|
{
|
|
|
|
target = none;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (publicConsole.GetLifeVersion() != publicConsoleLifeVersion) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private final function AnnounceTemplate(
|
|
|
|
ConsoleWriter writer,
|
|
|
|
TextTemplate template)
|
|
|
|
{
|
|
|
|
local MutableText result;
|
|
|
|
|
|
|
|
if (writer == none) return;
|
|
|
|
if (template == none) return;
|
|
|
|
if (!template.IsInitialized()) return;
|
|
|
|
|
|
|
|
template
|
|
|
|
.TextArg(P("instigator"), instigatorName)
|
|
|
|
.TextArg(P("target"), targetName);
|
|
|
|
result = template.CollectFormattedM();
|
|
|
|
writer.Write(result).Flush();
|
|
|
|
_.memory.Free(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
defaultproperties
|
|
|
|
{
|
|
|
|
}
|