Today (well, this evening, actually) I'll be taking some time to work on and explain for you all a new command I'm working up for Grey Men - the stalk command.
The command is actually basically done - I got the bulk of it completed around November 2021 - but it's been a while since I worked on it and other things have happened in the game since then, so the first thing I do is bring it back up to date with the master branch. Thankfully this proceeds without a hitch and as far as I can tell the master branch still exists, so I remain unfired for another day.
Here is what the stalk command does - copied from my comment above the function:
Code: Select all
/* Itesh 2021-11-15 stalk command for Gray Men:
-- sets a target against whom you have some locate ability (eg "far southwest or similar")
-- and OB bonuses ( 5 + clanlevel )
-- and limited target switching ( only TO target ) */
This might not actually be all it does at the moment, and I'm going to have read the code to check because as I frequently state I cannot remember last week usually, let alone last November.
So How Does This Work?
Well, pretty simply, actually.
First of all, we add three variables to the runtime-only (i.e not saved to playerfile) section of player memory. We don't need to save this at all, so using runtime data keeps things pretty simple and saves me from having to actually learn file saving and loading properly. Hurray!
We add:
- 1 int variable, probably called something like stalking_count
- 1 pointer to character data called something like "stalking"
- 1 pointer to character data called something like "stalked_by"
So we can keep count of how many successful stalks we've managed, and store pointers both to the person we are stalking, and the person that is stalking us.
Why do we need to store a pointer to the person stalking us? (you might ask)
Okay, let's imagine X is stalking Y. X has their pointer to Y saved:
Now, for instance, you can do stuff like this:
track(X->stalking) and you'll track where Y is. This is a made up function, by the way, that's not how track works.
Another example - X is fighting, and we need to check whether X is fighting the person they are stalking:
Code: Select all
if ( victim == X->stalking) {
DO ALL THE THINGS;
}
Y has a pointer pointing back to X:
Why might you need that? Here's one obvious example: Y logs off. Should we tell X their victim has gone? Probably, I would think. If you have a pointer, as part of the logoff process you can do something like this (and please appreciate I'm writing in shitty pseudocode here)
That's cleared X's pointer - because Y->stalked_by *is* X.
If we didn't have that pointer pointing backwards, the only other way I could see to do this would be to iterate through every single person online, checking their stalking pointers to see if they point to Y. So that's like, I dunno, 20-30 operations instead of 1.
Plus I copy a lot of my code and some other stuff is already set up this way, so it seems like best practice...
So structurally that's more or less how it's set up. There's a stalk command of course, and it has a bunch of checks - am I even a Grey Man? Am I trying to stalk an NPC (because lol no). Is your victim fighting?
If we get through the checks, you get some flavour text depending on your stalk count. At the moment it's one message for 0 and a different one for anything else:
You start to prey on %s.
You refine your approach to your prey.
...It's not very inspired at the moment, I know. For those of you unfamiliar with some of the C library functions, the %s token just means that at a later point, some variable or other will be slotted in there - in this case, our victim's name.
After this, one final quick quick that makes sure that the person we are now stalking is the same as the person we were stalking last time. And actually, it occurs to me that that should probably happen one block higher, before the text I've just mentioned.
TIMER TIMER WOOP WOOP er I mean, so we do a timer. And the length is dependent on the amount of 'stalks' you already have on the victim, and very mildly affected by your clan rank. Not, you know, that I've set up a clan for Grey Men yet, because I haven't, but I will definitely get to that.
The timer length is:
Code: Select all
MAX(8,6+(GET_STALKING_COUNT(ch) * GET_STALKING_COUNT(ch)) - GET_CLANLEVEL(ch))
So er. Jesus. How does this work again? I'm sure I had a spreadsheet of this.
Okay so I junked the spreadsheet because I am an imbecile, but I found an embed of it in the Grey Man test discord, and now I'm typing numbers from a split screen like a pleb:
Code: Select all
0 1 2 3 4 5 6 7 8 9
stalks
0 8 8 8 8 8 8 8 8 8 8
1 8 8 8 8 8 8 8 8 8 8
2 10 9 8 8 8 8 8 8 8 8
3 15 14 13 12 11 10 9 8 8 8
4 22 21 20 19 18 17 16 15 14 13
5 31 30 29 28 27 26 25 24 23 22
I expect there's zero chance this will render nicely on forums. Zero.
Cards on the table, I basically just ad-libbed the equation for this: my only objectives were to make higher-number stalks take an increasingly long time, and for clan rank to slight ameliorate the situation. Getting a really snazzy well-researched equation wasn't as important at the time as just getting it all to work.
You can have max five stalks, obviously. The first stalk sets your target, and subsequent stalks increment your count, so actually stalks = 1 means you've stalked *twice*. And this may be a stupid way to do it.
Post-timer, we have some flavour messages:
"You settle %s's routines in your mind, committing $S habits and routines to memory."
That $S will get replaced with an appropriate pronoun for your victim, depending on their gender.
So About This Locating Ability?
Yes, right. So, it seems logical to tie this to the sense command, which at the moment is Fade-only. I swift burst of logic that literally says 'if Grey Man, do this thing instead' forks us off to a completely different function which I am not ashamed to admit is a complete and utter copy of the innards of Locate Life - just using your stalking target as a, well, target.
If you don't have a target, it turns out I was feeling sassier than normal on the day I did this:
You sense nothing... except Shai'tan's disappointment.
...and other than that, it's *basically* the same as Locate Life, with the exception that the functional range is set to 5 + stalking count.
Zones have cartesian co-ordinates, and the distance is calculated thusly... you know what, actually, I'm writing this in Notepad and the symbols aren't there. Here is an online calculator:
https://www.calculatorsoup.com/calculat ... points.php
I can't do the maths, and the mud already has functions built in that do it! The real point is, zones have a range from one another, and Locate Life - and therefore, Grey Man sensing, has a range. Bleh, maths.
FWIW, Locate Life has a lot better range than the Grey Man version. And I'm not fixed on 5 + stalk number, either. We could wind that back, nothing is certain.
This version has port codes stripped out, of course, because those are pointless,
This is what it looks like - bear in mind this is from an early version, where the Dark One would select you a target at random. We don't do that any more.
HP:Healthy MV:Fresh > sense
You sense nothing... except Shai'tan's disappointment.
HP:Healthy MV:Fresh > stalk
The Great Lord speaks in your mind:
"END THE LIFE OF Testone, WORM.
"
HP:Healthy MV:Fresh > sense
Testone - somewhere around here.
And Those OB Bonuses?
I haven't coded this yet. My feeling is, that OB is recalculated for each person at the start of each combat round. We only want the Grey Men to have extra OB against their actual targets (because they're assassins, right?)
So in each call to calculate player bonuses, we're going to have to write something like this:
Code: Select all
if ( is_fighting(gman) && gman->opponent == gman->stalking) {
OB = 5 + get_stalking_count(gman);
}
...and that'll probably work. I'll want to talk through those numbers with someone though. A max of 10 extra OB might be a bit too much. We could do something like get_stalking_count * 3 / 2:
...which works kind of okay until you get to then, and then there you are too high again. But we have options, like doing a classic Aureus:
It's not really a classic Aureus because I understand what I just did and thinking through that equation doesn't summon Elder Gods from the Cthonic realms.
Edit: Shout out to Yeri for pointing out that my maths is wrong in the example above which I claimed to understand!
And the Target Switching...
Okay that one IS easy - the code is already there for Fade target switching, so just add another case to that where it checks that the person you're trying to switch to is your stalking target, and if it is, then do the necessary. Keep that focus on your target.
And that's basically it, so far. I'm more or less finished, except...
No Really, What Haven't You Done?
I basically just haven't dealt with clearing the pointers whenever anyone logs off or quits. So at the moment it's fine, except, you may try and follow a pointer to a character who is no longer in memory. And That Would Be Bad.
I was going to fix that tonight, but for the last hour or so Spawn has been resisting the idea of going to actual bed, so I'm going to eat ice cream instead.
Edit: Why Did You Do This?
Well, Grey Men were feeling a little underpowered in combat versus the other remorts. And this *might* help, versus their actual targets, at least. And it's kinda cool. It synergizes nicely with Shadowmask, which will give you the opportunity to hang around people running secret timers on them. I guess we'll see how it pans out, in testing.