This is a read only copy without any forum functionality of the old Modcraft forum.
If there is anything that you would like to have removed, message me on Discord via Kaev#5208.
Big thanks to Alastor for making this copy!

Menu

Author Topic: [C++] [WotLk] Real Stealth...  (Read 2765 times)

Scytheria23

  • Registred Member
  • LUA Script Tinker
  • *****
  • Posts: 49
    • View Profile
[C++] [WotLk] Real Stealth...
« on: March 12, 2016, 01:58:14 am »
This is going to be tricky.  I'm not requesting it, but any ideas or assistance is vastly appreciated.  I've started this thread because (1) it may be of interest to others and (2) somebody here may have an insight or brainwave that helps.

What I want to do:

Change the mechanics of Stealth (the Rogue ability) so that its effectiveness is dependent on the level of light around the character or npc using it.  In effect, to make Stealth much less of a binary affair - currently the ability puts you in two modes, hidden or unhidden, with no grey area.  I want a grey area, in which a model's transparency and statistical visibility varies by surrounding light.  I'm aiming to do this for WotLK on a Trinity Core, but am open to shifting client or server if a simple solution exists elsewhere.

Problems:

WoW, as far as I can tell, does not have any mechanisms for tracking the level of light falling on a model.  Certainly, the client must be passing information to the graphics hardware about this, but it's not information contained in parcels sent between the client and server.  The information is only sent from client to hardware.  Since client source code is (practically) unavailable, I will need to do something to the Trinity Core to make this work.

Vague Idea:

Add invisible (GM view only) gameobjects to maps wherever I want there to be light.  I'll call these 'LightMarkers' for simplicity.  These, of course, do not actually create light that players can see, but they simply mark light intensity.  Let's have a range of Lightmarkers (Lightmarker0, Lightmarker1, Lightmarker2 ... Lightmarker 10) for a good range of light levels ranging from 0 to 10.

For example, in-game there's a torch on a wall.  I want this to have a low light intensity, so I place an invisible Lightmarker3 on the same spot.  The players can't see it, but it's there all the same.

The position of a model relative to any nearby Lightmarkers is calculated, and some formula or other changes the intensities and the player's distance from the Lightmarkers into a figure that I'll call 'Exposure'.  Exposure ranges from 0 (complete darkness) to 1 (full, bright light).  Move closer to a Lightmarker, and Exposure increases.  Move away, it decreases.

The Stealth ability's code now gets re-worked to scale Stealth by the model's current Exposure.  I'm not sure yet, but I'm hoping this can be dynamic (e.g. if you enter Stealth in complete darkness and then move into bright light, your Stealth efficiency changes).

Pitfalls:

I'm not sure this system will work so well if Lightmarkers are, for example, behind something.  For example, if you are standing next to a wall, and there's a Lightmarker on the other side of it, your Exposure will increase... Maybe will need to give Lightmarkers a direction too?

Additional:

As well as the above, I'd ideally like the armour/weapons a model is using and its actions to have a noticeable effect on Stealth.  Wear more armour, your Stealth decreases.   Draw a weapon, your Stealth Decreases.  Move, your Stealth decreases (based on your movement speed).  Etc.

Why?

Good question.  I'll be starting a 'What are you working on?' in a short while.  Thanks for reading!

Scy
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Ascathos

  • Moderators
  • Creator of Worlds
  • *****
  • Posts: 1129
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #1 on: March 13, 2016, 03:51:32 am »
Well, that is indeed tricky. But possible. Have lightmarkers shine in an area and make an Line of Sight check, if that fails it wouldn't affect it.

You could judge by armor type (cloth, leather, mail, etc.) and, if you want, certain armor entries to provide more or less light restriction.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Caedes

  • Registred Member
  • MS Paint Freak
  • *****
  • Posts: 4
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #2 on: March 26, 2016, 07:24:02 pm »
Hey, I'm new here.

My thoughts for your problem are a bit rough, but might be helpful.

Armor Type: You could add some variation of the Night Elf racial that increases ones stealth level to leather/cloth type gear and lower the the general stealth level, that stealth abilities provide, for balancing reasons.

Light Sources: Same idea actually, you can create invisible units that provide an aura that decreases the stealth levels of units within a specific range.

The change to how Stealth works: the way your Stealth is supposed to work reminded me a bit of how Camouflage works (if I understood you right). You could generally decrease the stealth level of units to make them visible within a larger circle but add an additional effect that works similar to Cata's Camouflage (ranged dps' can't attack whereas melees can + standing still makes you completely invisible).

Another solution for the stealth-movement-speed-scaling could be a group of auras that decrease the range of spells that can be used on your stealthed target (no idea how Camouflage is coded, but there might be something that can be used for that) and increase stealth level. You could add dummy auras (that do nothing) to spells that increase movement that replace those Camouflage auras like high ranked buffs do with lower rank buffs of the same group. That would also work with my previous idea (adding those dummy auras to gear (the heavier the gear, the more dummy auras are on it) and light sources (the more light a light source provides, the more dummy auras are present, although I think that would make the number of dummy auras ridiculous)).

I hope my ideas are of any help.

regards, Caedes
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Scytheria23

  • Registred Member
  • LUA Script Tinker
  • *****
  • Posts: 49
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #3 on: April 18, 2016, 02:55:01 am »
Thanks for the above suggestions.

Just an update on progress.  My approach has changed somewhat, now much less to do with coding.  Here are the steps taken so far:

[1] Stealth (the rogue ability) has now been turned into a passive ability that is on all the time.  It's visual effects (e.g. translucency and animations, speed reduction) have been removed.  This means that characters can sneak up on npcs, and as long as they stay behind them are mostly undetectable.  This is, of course, an improvement on the existing system in WoW where npcs have 360 vision.

[2] A new spell, a clone of the original Stealth, can be learned to enhance the passive stealth.  This has the usual visual effects and animations.

[3] Light markers (invisible gameobjects) radiate stackable debuffs that decrease stealth.  The nearer you are to a marker, the more it stacks.

This seems to work pretty well, but there are some bugs to iron out with line of sight, etc.  I'm also not totally happy with the passive stealth which seems a little too powerful (e.g. you can stand still right in front of an npc without being detected).  This should, hopefully, be a case of fine-tuning some of the spell variables.

Scy
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

iindigo

  • Registred Member
  • Wiki Incarnate
  • *****
  • Posts: 198
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #4 on: April 18, 2016, 05:22:49 pm »
For outdoor areas you might be able to modify the server core to be able to read static/baked shadow maps from ADTs. This would work similarly to how vamp extraction works, reading ADTs and converting the desired information into something more readable. The server can then factor them into stealth calculations.

Obviously this wouldn't help for light sources like torches but it would reduce the amount of manual light marker placement work necessary.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Kaev

  • Contributors
  • Creator of Worlds
  • *****
  • Posts: 308
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #5 on: April 19, 2016, 08:24:46 am »
That sounds really awesome. Would love to see the outcome!
Quote from: "Scytheria23"
This seems to work pretty well, but there are some bugs to iron out with line of sight, etc.  I'm also not totally happy with the passive stealth which seems a little too powerful (e.g. you can stand still right in front of an npc without being detected).  This should, hopefully, be a case of fine-tuning some of the spell variables.
I don't know how they implemented the stealth mechanism, but i doubt that you can do that with some spell variables.
Good thing: The server knows the orientation of the NPC, so you can calculate the area where the NPC could see the player.
Bad thing: You probably have to mess with the whole line of sight and/or stealth detection system in your core.

EDIT: I thought 5 minutes about it and maybe it would be enough to implement a custom CanSeeOrDetect method, do the calculation if the player is in front of the NPC somewhere and return true.
Not sure atm, but this should be the CanSeeOrDetect method that the NPCs are using: https://github.com/TrinityCore/TrinityC ... .cpp#L1940

EDIT2: There's even a CanDetectStealthOf method :) https://github.com/TrinityCore/TrinityC ... .cpp#L2068
But be careful, this is the only CanDetectStealthOf method in the whole project, which means you will change it for every single thing in the game. Example given: As a player, you'll only detect invisible NPCs infront of you too.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Scytheria23

  • Registred Member
  • LUA Script Tinker
  • *****
  • Posts: 49
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #6 on: May 20, 2016, 10:01:28 am »
Another update.  I'll get some vids online sometime soon to show how this is going...

Thanks to Kaev, for some very interesting ideas - these have totally reshaped my mechanism, but the new system is far more robust and works very nicely.  I'll try to explain the main points:

(1) All players and NPCs now 'see' in an arc rather than having 360 vision.
(2) The size of the arc is increased by having high intellect (e.g. perception).
(3) The size of the arc is decreased, however, by an approaching unit's agility (e.g. stealth).
(4) The distance a player/NPC can see is increased by intellect.
(5) Thus, it is possible to follow any player/NPC (at a reasonable distance) without being seen regardless of any stealth ability.  More perceptive units will spot you sooner, and you will need to move in a tighter zone to remain hidden.  More agile units will be able to follow closer and in a wider zone.
(6) Bulky armor and weapons improve resistance to physical damage  and cause damage (of course) but reduce Agility.  This effect can be mitigated by having a higher Strength.  Armor and weapons in bags also count towards this effect.
(7) The stealth ability is learnable (actually, talentable) and allows guaranteed invisibility when behind a unit's visual arc and a chance to be undetected when in front of it.
(8) Lights emit stealth debuffs.

So, this is pretty much doing everything I wanted and without too much fiddling around.  The only part of the Trinity Core modified (and heavily) is the CanDetectStealthOf function in object.cpp.  This required a total rewriting, but remains compatible with the other things it handled.  All I need to do next is somehow factor footsteps in to make a perfect system.  Ideally, walking on things like tiles or metal plates should make noise and reduce all kinds of stealth.  Not sure even where to begin on that, but something, somewhere knows when a unit walks on different textures to play different sounds or leave different footprints... clues welcomed.

Scy
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Ascathos

  • Moderators
  • Creator of Worlds
  • *****
  • Posts: 1129
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #7 on: May 20, 2016, 11:14:41 am »
I'd love to see videos about this.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Scytheria23

  • Registred Member
  • LUA Script Tinker
  • *****
  • Posts: 49
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #8 on: May 23, 2016, 12:39:02 am »
Due to my geographical location (e.g. China) where access to Youtube and similar sites is blocked, I'm going to have to hold up on providing videos until I get back to the UK for the summer.  Meanwhile, in the spirit of sharing, I provide my code changes to object.cpp which replace the entire existing CanDetectStealthOf function. Don't poke at my coding style - I'm a mathematician, not a coder - this gets the job done.

If you choose to try out this system, you will need to make a few adjustments to suit your core because my own is heavily modified from Blizzlike parameters.  My own project dispenses with levels entirely, attributes are in the range 0-200 only and stealth abilities award bonuses that only extend up to +100 stealth points.  If, for example, you want a unit's level to factor into this or the level of the potential observer, you will need to figure that out yourself.  If your stats are in the normal Blizzlike range, you'll need to play with the default values of v_intellect and o_agility and the bits of code that restrain them.  

The below code does not do anything to create light emitters.  I'm still working on that aspect, but am tinkering with the go type 30 (aura emitters) or a disused type (as Trinity Core already achieves things that way).

Anyway, use, abuse and enjoy.

Code: [Select]
// Real Stealth

bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) const
{
float distance = GetExactDist(obj);
float combatReach = 0.0f;

float v_intellect = 100.0f;
float o_agility = 100.0f;

float viewarc = (float(M_PI) * 1.25);
float radiusinner = 0.0f;
float radiusmiddle = 10.0f;
float radiusouter = 20.0f;

Unit const* v_unit = ToUnit();
Player const* v_player = ToPlayer();
Unit const* o_unit = obj->ToUnit();
Player const* o_player = obj->ToPlayer();

int32 sneakbonus = 100;
float sneakscale = 1.0f;

// if object is not a player and has no stealth return true (visible at all times)
// do this now to prevent running through the entire function for no good reason
if (!(o_unit->GetTypeId() == TYPEID_PLAYER) && !(o_player) && !(obj->m_stealth.GetFlags())) return true;

if (v_unit)
{
       combatReach = v_unit->GetCombatReach();
       if ((v_unit->GetTypeId() == TYPEID_PLAYER) && (v_player)) v_intellect = v_player->GetStat(STAT_INTELLECT);
}

   if ((o_unit->GetTypeId() == TYPEID_PLAYER) && (o_player)) o_agility = o_player->GetStat(STAT_AGILITY);

if (v_intellect < 1.0f) v_intellect = 1.0f;
if (o_agility < 1.0f) o_agility = 1.0f;
if (v_intellect > 200.0f) v_intellect = 200.0f;
if (o_agility > 200.0f) o_agility = 200.0f;

viewarc = viewarc * (v_intellect / o_agility);
if (viewarc > (float(M_PI) * 1.5f)) viewarc = (float(M_PI) * 1.5f);
if (viewarc < (float(M_PI) / 2.0f)) viewarc = (float(M_PI) / 2.0f);

for (uint32 i = 0; i < TOTAL_STEALTH_TYPES; ++i)
{
if (!(obj->m_stealth.GetFlags() & (1 << i))) continue;

if (v_unit && v_unit->HasAuraTypeWithMiscvalue(SPELL_AURA_DETECT_STEALTH, i)) return true;

sneakbonus -= m_stealthDetect.GetValue(StealthType(i));
sneakbonus += obj->m_stealth.GetValue(StealthType(i));
}

if (sneakbonus < 0) sneakbonus = 0;
if (sneakbonus > 100) sneakbonus = 100;

sneakscale = ((float(sneakbonus) / 100.f) * (o_agility / v_intellect));

radiusinner = combatReach;
radiusmiddle = radiusinner + 15.0f - (5.0f * sneakscale);
radiusouter = radiusmiddle * 2.0f;

if (radiusmiddle < radiusinner) radiusmiddle = radiusinner + 1.0f;
if (radiusouter < radiusmiddle) radiusouter = radiusmiddle + 2.0f;

if (checkAlert) radiusinner += (radiusinner * 0.08f) + 1.5f;
if (checkAlert) radiusmiddle += (radiusmiddle * 0.04f) + 1.0f;
if (checkAlert) radiusouter += (radiusouter * 0.02f) + 0.5f;

// always detect things in combat reach
if (distance < radiusinner) return true;

// always detect things within the front middle arc
if ((distance < radiusmiddle) && (HasInArc(viewarc, obj))) return true;

// always detect unstealthed things within the rear middle arc
if ((distance < radiusmiddle) && !(HasInArc(viewarc, obj)) && !(obj->m_stealth.GetFlags())) return true;

// always detect unstealthed things within the front outer arc
if ((distance < radiusouter) && (HasInArc(viewarc, obj)) && !(obj->m_stealth.GetFlags())) return true;

// otherwise thing is not detected
return false;
}
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Scytheria23

  • Registred Member
  • LUA Script Tinker
  • *****
  • Posts: 49
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #9 on: May 23, 2016, 03:19:50 am »
Just a quick point for anyone trying this - you will note that non-stealthed players become invisible to you when they are stood a certain distance behind you.  This applies to enemies and allies alike.  Essentially, they are beyond your visual arc.  This is realistic (e.g. I can't see people standing behind me even if they are my friends), but possibly undesirable in a Blizzy environment (especially if you like mouse-wheeling out your view and panning around).  You probably don't want half a raid group appearing to vanish just because they are stood behind you, so an additional condition will ne needed somewhere.  In my project, where players can freely attack, kill and rob any other player, this effect is desired.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Kaev

  • Contributors
  • Creator of Worlds
  • *****
  • Posts: 308
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #10 on: May 23, 2016, 10:06:27 am »
Thanks for sharing your code and ideas! Imo the entire idea is still pretty awesome. Even better that you really could create something like you imagined!

If possible somehow you can upload your video on a file uploading site or send it via skype or whatever you can and i'll upload it for you.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Ascathos

  • Moderators
  • Creator of Worlds
  • *****
  • Posts: 1129
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #11 on: May 23, 2016, 03:37:04 pm »
« Last Edit: January 01, 1970, 01:00:00 am by Admin »

Scytheria23

  • Registred Member
  • LUA Script Tinker
  • *****
  • Posts: 49
    • View Profile
Re: [C++] [WotLk] Real Stealth...
« Reply #12 on: May 24, 2016, 12:37:04 am »
Well thank you, Ascathos (I think).

I feel the need to explain how this code can be tweaked to fit projects other than my own.

(1) Attributes

You'll need to decide a 'cap' for both intellect and agility.  Players can have attributes over this cap, but doing so will not improve either perception or stealth.  In my project, both are capped at 200, but in a normal WotLK game this will need to be a lot higher (maybe 2000?) - I forget how high attributes get.

You'll also need to decide what constitutes a base score for both - e.g. what a normal max-level NPC should have.  In my project, this is 100.  In a WotLK game, this must be higher - typically half of the cap.

Change the code as follows:

Code: [Select]
float v_intellect = YOUR INT BASE AS A FLOAT;
float o_agility = YOUR AGI BASE AS A FLOAT;

and

Code: [Select]
if (v_intellect < 1.0f) v_intellect = 1.0f;
if (o_agility < 1.0f) o_agility = 1.0f;
if (v_intellect > YOUR INT CAP AS A FLOAT) v_intellect = YOUR INT CAP AS A FLOAT;
if (o_agility > YOUR AGI CAP AS A FLOAT) o_agility = YOUR AGI CAP AS A FLOAT;

(2) Stealth/Perception Bonuses

If you have not done anything to the WotLK spells, use this:

Code: [Select]
int32 sneakbonus = 350;
and

Code: [Select]
if (sneakbonus > 350) sneakbonus = 350;
(3) Ranges


You can tinker with the ranges of the view arcs with these:

Code: [Select]
radiusinner = combatReach;
radiusmiddle = radiusinner + XXX - (YYY * sneakscale);
radiusouter = radiusmiddle * ZZZ;

XXX = base radius in which all are detected irrespective of stealth
YYY = amount that XXX can be reduced by stealth (I suggest about 1/3 of XXX)
ZZZ = multiplier of base radius in which unstealthed are detected when in front (must be more than 1, I suggest 2+)

(4) Player and NPC levels

Since this system is based around attribute scores and since attribute scores typically increase with level, there's no real need to incorporate these.  Having said that, all NPCs will have the same base perception.  I'm happy with this - you don't really get better eyesight the more experienced a warlock you are.
« Last Edit: January 01, 1970, 01:00:00 am by Admin »