Browse Source

Add god command

feature_improvement
Anton Tarasenko 2 years ago
parent
commit
806813359c
  1. 205
      sources/Commands/ACommandGod.uc
  2. 225
      sources/Commands/ACommandGod_Announcer.uc
  3. 1
      sources/Futility_Feature.uc

205
sources/Commands/ACommandGod.uc

@ -0,0 +1,205 @@
/**
* Command for making player immortal.
* 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 ACommandGod extends Command;
struct GodStatus
{
// Player to whom we grant godhood
var EPlayer target;
// Is `target` only a demigod (can get damaged, but not die)?
var bool demigod;
// Should `target` be unaffected by attacks momentum?
var bool unmovable;
};
var private array<GodStatus> godhoodList;
var private ACommandGod_Announcer announcer;
var private const int TDAMAGE, TMOMENTUM;
protected function Finalizer()
{
_.memory.Free(announcer);
_.kf.health.OnDamage(self).Disconnect();
super.Finalizer();
}
protected function BuildData(CommandDataBuilder builder)
{
builder.Name(P("god")).Group(P("gameplay"))
.Summary(P("Command for making player immortal."));
builder.RequireTarget()
.Describe(P("Gives targeted players god status, making them"
@ "invincible."));
builder.SubCommand(P("list"))
.Describe(P("Reports godhood status of targeted players."));
builder.SubCommand(P("strip"))
.Describe(P("Strips targeted players from the godhood status."));
builder.Option(P("demi"))
.Describe(P("This flag makes targeted players \"demigods\" instead -"
@ "they still cannot die, but they can take any non-lethal"
@ "damage."));
builder.Option(P("unmovable"))
.Describe(P("This flag also prevents targeted players from being"
@ "affected by the momentum trasnferred from damaging attacks."));
announcer = ACommandGod_Announcer(
_.memory.Allocate(class'ACommandGod_Announcer'));
_.kf.health.OnDamage(self).connect = ProtectDivines;
}
protected function ExecutedFor(
EPlayer target,
CallData arguments,
EPlayer instigator)
{
local GodStatus newGodStatus;
announcer.Setup(target, instigator, othersConsole);
if (arguments.subCommandName.IsEmpty())
{
newGodStatus.target = target;
newGodStatus.demigod = arguments.options.HasKey(P("demi"));
newGodStatus.unmovable = arguments.options.HasKey(P("unmovable"));
MakeGod(target, newGodStatus);
}
else if (arguments.subCommandName.Compare(P("list"))) {
announcer.AnnounceGodStatus(BorrowGodStatus(target));
}
else if (arguments.subCommandName.Compare(P("strip"))) {
RemoveGod(target);
}
}
private function ProtectDivines(
EPawn target,
EPawn instigator,
HashTable damageData)
{
local int damage;
local EPlayer targetedPlayer;
local GodStatus targetDivinity;
targetedPlayer = target.GetPlayer();
targetDivinity = BorrowGodStatus(targetedPlayer);
_.memory.Free(targetedPlayer);
if (targetDivinity.target == none) {
return;
}
if (targetDivinity.unmovable) {
damageData.SetVector(T(TMOMENTUM), Vect(0.0f, 0.0f, 0.0f));
}
if (targetDivinity.demiGod)
{
damage = damageData.GetInt(T(TDAMAGE));
damage = Min(damage, target.GetHealth() - 1);
damageData.SetInt(T(TDAMAGE), damage);
}
else {
damageData.SetInt(T(TDAMAGE), 0);
}
}
private final function MakeGod(
EPlayer target,
GodStatus newGodStatus)
{
local int godIndex;
local bool wasGod;
local GodStatus oldGodStatus;
if (target == none) {
return;
}
for (godIndex = 0; godIndex < godhoodList.length; godIndex += 1)
{
if (target.SameAs(godhoodList[godIndex].target))
{
wasGod = true;
oldGodStatus = godhoodList[godIndex];
break;
}
}
if (wasGod)
{
if ( newGodStatus.demiGod == oldGodStatus.demiGod
&& newGodStatus.unmovable == oldGodStatus.unmovable)
{
announcer.AnnounceSameGod(newGodStatus);
}
else
{
announcer.AnnounceChangedGod(oldGodStatus, newGodStatus);
godhoodList[godIndex].target.FreeSelf();
newGodStatus.target.NewRef();
godhoodList[godIndex] = newGodStatus;
}
}
else {
announcer.AnnounceNewGod(newGodStatus);
newGodStatus.target.NewRef();
godhoodList[godhoodList.length] = newGodStatus;
}
}
private final function RemoveGod(EPlayer target)
{
local int i;
if (target == none) {
return;
}
for (i = 0; i < godhoodList.length; i += 1)
{
if (target.SameAs(godhoodList[i].target))
{
announcer.AnnounceRemoveGod(godhoodList[i]);
godhoodList[i].target.FreeSelf();
godhoodList.Remove(i, 1);
return;
}
}
announcer.AnnounceWasNotGod();
}
private final function GodStatus BorrowGodStatus(EPlayer target)
{
local int i;
local GodStatus emptyStatus;
if (target == none) {
return emptyStatus;
}
for (i = 0; i < godhoodList.length; i += 1)
{
if (target.SameAs(godhoodList[i].target)) {
return godhoodList[i];
}
}
return emptyStatus;
}
defaultproperties
{
TDAMAGE = 0
stringConstants(0) = "damage"
TMOMENTUM = 1
stringConstants(1) = "momentum"
}

225
sources/Commands/ACommandGod_Announcer.uc

@ -0,0 +1,225 @@
/**
* Announcer for `ACommandGod`.
* 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 ACommandGod_Announcer extends CommandAnnouncer
dependson(ACommandGod);
var private AnnouncementVariations godStatus, newGod, removeGod, sameGod;
var private AnnouncementVariations changedGod, wasNotGod;
protected function Finalizer()
{
FreeVariations(godStatus);
FreeVariations(newGod);
FreeVariations(removeGod);
FreeVariations(sameGod);
FreeVariations(changedGod);
FreeVariations(wasNotGod);
super.Finalizer();
}
public final function AnnounceGodStatus(ACommandGod.GodStatus status)
{
local int i;
local MutableText statusAsText;
local array<TextTemplate> templates;
if (!godStatus.initialized)
{
godStatus.initialized = true;
godStatus.toSelfReport = _.text.MakeTemplate_S(
"You're %1");
godStatus.toOtherReport = _.text.MakeTemplate_S(
"%%target%% is %1");
}
statusAsText = DisplayStatus(status);
templates = MakeArray(godStatus);
for (i = 0; i < templates.length; i += 1) {
templates[i].Reset().Arg(statusAsText);
}
_.memory.Free(statusAsText);
MakeAnnouncement(godStatus);
}
public final function AnnounceNewGod(ACommandGod.GodStatus status)
{
local int i;
local MutableText statusAsText;
local array<TextTemplate> templates;
if (!newGod.initialized)
{
newGod.initialized = true;
newGod.toSelfReport = _.text.MakeTemplate_S(
"You {$TextPositive made} yourself %1");
newGod.toSelfPublic = _.text.MakeTemplate_S(
"%%instigator%% {$TextPositive made} themselves %1");
newGod.toOtherReport = _.text.MakeTemplate_S(
"You {$TextPositive made} %%target%% %1");
newGod.toOtherPrivate = _.text.MakeTemplate_S(
"%%instigator%% {$TextPositive made} you %1");
newGod.toOtherPublic = _.text.MakeTemplate_S(
"%%instigator%% {$TextPositive made} %%target%% %1");
}
statusAsText = DisplayStatus(status);
templates = MakeArray(newGod);
for (i = 0; i < templates.length; i += 1) {
templates[i].Reset().Arg(statusAsText);
}
_.memory.Free(statusAsText);
MakeAnnouncement(newGod);
}
public final function AnnounceRemoveGod(ACommandGod.GodStatus status)
{
local int i;
local MutableText statusAsText;
local array<TextTemplate> templates;
if (!removeGod.initialized)
{
removeGod.initialized = true;
removeGod.toSelfReport = _.text.MakeTemplate_S(
"You, %1, {$TextNegative became} a mere {$TextNegative mortal}");
removeGod.toSelfPublic = _.text.MakeTemplate_S(
"%1 %%instigator%% {$TextNegative made} themselves a mere"
@ "{$TextNegative mortal}");
removeGod.toOtherReport = _.text.MakeTemplate_S(
"%1 %%target%% was {$TextNegative made} a mere"
@ "{$TextNegative mortal} by you");
removeGod.toOtherPrivate = _.text.MakeTemplate_S(
"You, %1, was {$TextNegative made} a mere {$TextNegative mortal}"
@ "by %%instigator%%");
removeGod.toOtherPublic = _.text.MakeTemplate_S(
"%1 %%target%% was {$TextNegative made} a mere"
@ "{$TextNegative mortal} by %%instigator%%");
}
statusAsText = DisplayStatus(status);
templates = MakeArray(removeGod);
for (i = 0; i < templates.length; i += 1) {
templates[i].Reset().Arg(statusAsText);
}
_.memory.Free(statusAsText);
MakeAnnouncement(removeGod);
}
public final function AnnounceSameGod(ACommandGod.GodStatus status)
{
local int i;
local MutableText statusAsText;
local array<TextTemplate> templates;
if (!sameGod.initialized)
{
sameGod.initialized = true;
sameGod.toSelfReport = _.text.MakeTemplate_S(
"You are already %1");
sameGod.toOtherReport = _.text.MakeTemplate_S(
"%%target%% is already %1");
}
statusAsText = DisplayStatus(status);
templates = MakeArray(sameGod);
for (i = 0; i < templates.length; i += 1) {
templates[i].Reset().Arg(statusAsText);
}
_.memory.Free(statusAsText);
MakeAnnouncement(sameGod);
}
public final function AnnounceChangedGod(
ACommandGod.GodStatus oldStatus,
ACommandGod.GodStatus newStatus)
{
local int i;
local MutableText oldStatusAsText, newStatusAsText;
local array<TextTemplate> templates;
if (!changedGod.initialized)
{
changedGod.initialized = true;
changedGod.toSelfReport = _.text.MakeTemplate_S(
"You, %1, {$TextPositive made} yourself %2");
changedGod.toSelfPublic = _.text.MakeTemplate_S(
"%1 %%instigator%% {$TextPositive made} themselves %2");
changedGod.toOtherReport = _.text.MakeTemplate_S(
"You {$TextPositive made} %1 %%target%% into %1");
changedGod.toOtherPrivate = _.text.MakeTemplate_S(
"%%instigator%% {$TextPositive made} you, %1, into %2");
changedGod.toOtherPublic = _.text.MakeTemplate_S(
"%%instigator%% {$TextPositive made} %1 %%target%% into %2");
}
oldStatusAsText = DisplayStatus(oldStatus);
newStatusAsText = DisplayStatus(newStatus);
templates = MakeArray(changedGod);
for (i = 0; i < templates.length; i += 1) {
templates[i].Reset().Arg(oldStatusAsText).Arg(newStatusAsText);
}
_.memory.Free(oldStatusAsText);
_.memory.Free(newStatusAsText);
MakeAnnouncement(changedGod);
}
public final function AnnounceWasNotGod()
{
local int i;
local array<TextTemplate> templates;
if (!sameGod.initialized)
{
sameGod.initialized = true;
sameGod.toSelfReport = _.text.MakeTemplate_S(
"You are already a mere {$TextNegative mortal}");
sameGod.toOtherReport = _.text.MakeTemplate_S(
"%%target%% is already a mere {$TextNegative mortal}");
}
templates = MakeArray(sameGod);
for (i = 0; i < templates.length; i += 1) {
templates[i].Reset();
}
MakeAnnouncement(sameGod);
}
private final function MutableText DisplayStatus(ACommandGod.GodStatus status)
{
local MutableText builder;
builder = _.text.Empty();
if (status.target == none)
{
builder.Append(F("a mere {$TextNegative mortal}"));
return builder;
}
if (status.unmovable) {
builder.Append(F("an {$TextPositive unmovable}, "));
}
else {
builder.Append(F("a {$TextNeutral simple}, "));
}
if (status.demigod) {
builder.Append(F("immortal {$TextNeutral demigod}"));
}
else {
builder.Append(F("invincible {$TextPositive god}"));
}
return builder;
}
defaultproperties
{
}

1
sources/Futility_Feature.uc

@ -78,5 +78,6 @@ defaultproperties
allCommandClasses(3) = class'ACommandDB'
allCommandClasses(4) = class'ACommandInventory'
allCommandClasses(5) = class'ACommandFeature'
allCommandClasses(6) = class'ACommandGod'
errNoCommandsFeature = (l=LOG_Error,m="`Commands_Feature` is not detected, \"Futility\" will not be able to provide its functionality.")
}
Loading…
Cancel
Save