Wed Jan 19, 2022 5:45 pm
Spoiler:
Thu Jan 20, 2022 2:13 am
Sir Robin wrote:is there any existing functionality similar to this already happening that I can leverage?
Sir Robin wrote:where are the best places to fire that LineTrace from and where to store it's FLineTraceData where the statusbar and weapon can pick it up?
Thu Jan 20, 2022 6:30 pm
Player701 wrote:Sir Robin wrote:is there any existing functionality similar to this already happening that I can leverage?
First of all, note that UI code can only read the playsim data. This means that if you do a line trace from your HUD code, you can only use the trace result to describe what kind of attack (if any) your weapon will peform, but you won't have access to this data in your weapon code when it actually performs an attack. For both the HUD and the weapon to be able to access the trace result and act on it, the code that does the trace has to be on the playsim side. I suggest you put this functionality in your player class code - this way, your HUD will be able to access the result to provide descriptions for generic actions (e.g. look, use etc.), and your weapons will use it both to provide descriptions for their attacks (queried by the HUD) as well as to actually pick an attack in the fire state.
Thu Jan 20, 2022 11:10 pm
Fri Jan 21, 2022 3:35 am
Sir Robin wrote:I found a function called Tick() that gets called every tic. That's only 35 times a second, so on games running 60 or 90 or 120 FPS, it's only getting called about every 2nd, 3rd, or 4th frame. That seems kinda slow but until I find a better place, I'll try this.
Sir Robin wrote:I did figure out how to create custom user CVARs and put my trace data in a string there. Then I can go to the console and print the string manually from there.
Sir Robin wrote:So that tells me that the player actor isn't the one calling the tick() function.
Tick()
for your player class (the one you inherit from PlayerPawn or DoomPlayer or some other built-in player). If you want call it from an inventory item (e.g. weapon) instead, then you will have to use the owner pointer:override void Tick()
{
Super.Tick();
if (Owner != null)
{
Owner.LineTrace(...);
// TODO: do stuff based on the trace result
}
}
Fri Jan 21, 2022 11:36 am
Player701 wrote:for some reason, you cannot actually use LineTrace from ui context (I don't really know why, as it doesn't seem to modify any game data), you will have to use LineTracer instead.
bool Trace(vector3 start, Sector sec, vector3 direction, double maxDist, ETraceFlags traceFlags)
Player701 wrote:Note that you can store the data directly in your actor(s), so a CVAR would only be useful for debugging. You shouldn't use a CVAR to store data for later use by your code, since it can be modified by the user at will; also, accessing user CVARs from ZScript code requires extra care to avoid breaking multiplayer.
Player701 wrote:You should overrideTick()
for your player class (the one you inherit from PlayerPawn or DoomPlayer or some other built-in player).
bool HasTargetLook;
FLineTraceData TargetLook;
property HasTargetLook: HasTargetLook;
property HasTargetAlt: HasTargetAlt;
override void Tick(){
//This has something to do with Voodoo dolls
if (!player || !player.mo || player.mo != self){
Super.Tick();
return;
}
Super.Tick();
HasTargetLook = LineTrace(
angle,
4096,
pitch,
TRF_THRUHITSCAN || TRF_ALLACTORS,
offsetz: ViewHeight,
data: TargetLook
);
CVar UW_PlayerLook = CVar.FindCVar('UW_PlayerLook');
String LookDescription='[null]';
if (HasTargetLook){
switch(TargetLook.HitType){
case TRACE_HitNone: LookDescription='nothing'; break;
case TRACE_HitFloor: LookDescription='floor'; break;
case TRACE_HitCeiling: LookDescription='ceiling'; break;
case TRACE_HitWall: LookDescription='wall'; break;
case TRACE_HitActor: LookDescription='actor'; break;
case TRACE_CrossingPortal: LookDescription='portal'; break;
case TRACE_HasHitSky: LookDescription='sky'; break;
}
LookDescription=LookDescription..' distance='..TargetLook.Distance;
Actor.Spawn("UW_CursorPuff",TargetLook.HitLocation);
} else {
LookDescription='not a damn thing';
}
UW_PlayerLook.SetString(LookDescription);
}
Fri Jan 21, 2022 11:58 am
Fri Jan 21, 2022 12:03 pm
Sir Robin wrote:even though that linetrace is in the player tick, it's originating from (0,0,0), so that tells me that the player doesn't actually call the tick function.
Sir Robin wrote:
- Code:
HasTargetLook = LineTrace(
angle,
4096,
pitch,
TRF_THRUHITSCAN || TRF_ALLACTORS,
offsetz: ViewHeight,
data: TargetLook
);
||
operator here, which returns true (1) if at least one of its operands is true. Both TRF_THRUHITSCAN
and TRF_ALLACTORS
are non-zero constants, so they evaluate to true, which means the result is also true, or 1, which also happens to be the value of TRF_ABSPOSITION
. This is why the origin of the trace is always at zero. To fix this, use the bitwise "or" |
instead of the logical "or" ||
.Sir Robin wrote:
- Code:
property HasTargetLook: HasTargetLook;
property HasTargetAlt: HasTargetAlt;
Default
block of the class definition. Only this part is enough to access the values as well as modify them (except from the ui context):Sir Robin wrote:
- Code:
bool HasTargetLook;
FLineTraceData TargetLook;
Sir Robin wrote:And how do I get direction from the player's angle and pitch?
double pc = pitch.Cos();
direction = { pc * angle.Cos(), pc * angle.Sin(), -pitch.Sin() };
double pc = Cos(pitch);
let direction = (pc * Cos(angle), pc * Sin(angle), -Sin(pitch));
Fri Jan 21, 2022 8:32 pm
Player701 wrote:You are using the logical "or"||
operator here, which returns true (1) if at least one of its operands is true. BothTRF_THRUHITSCAN
andTRF_ALLACTORS
are non-zero constants, so they evaluate to true, which means the result is also true, or 1, which also happens to be the value ofTRF_ABSPOSITION
. This is why the origin of the trace is always at zero. To fix this, use the bitwise "or"|
instead of the logical "or"||
.
Player701 wrote:Actor properties are only useful for setting up inherited classes, they are only used in theDefault
block of the class definition.
Player701 wrote:This is a bit tricky, because it requires some trigonometry.
- Code:
double pc = Cos(pitch);
let direction = (pc * Cos(angle), pc * Sin(angle), -Sin(pitch));
Sat Jan 22, 2022 11:16 am
Actor.Spawn("UW_CursorPuff",TargetLook.HitLocation);
char(toInt(min(max(value,0.0),1.0)*25)+65)
FrameNumber=mod(toInt(WorldTickCount/TicsPerFrame),FrameCount)
Sat Jan 22, 2022 1:56 pm
Sir Robin wrote:In this line of code I'm spawning a cursor as a puff that exists for only 1 frame. I do this to mark where the LineTrace hit. A few issues with this:
On certain walls (seems to be only 1-sided walls) the puff doesn't show up at all. I haven't been able to determine what walls it works with and what it doesn't - it doesn't seem to be related to direction or height or anything else I can figure out. I can have 2 linedefs, attacked to the same sector, at the same angles, and one works and the other doesn't.
On certain walls (seems to be only 2-sided walls where it hit a lower texture) the actor crawls up the wall, even though the puff vertical speed is set to 0.
What's causing these issues and how to correct them?
UW_CursorPuff
class is coded, so if you could post its code here, I might be able to tell you what's wrong with it.Sir Robin wrote:Other thing: the actor is always drawn perpendicular to the player. Is there an automatic way to change it's pitch and rotation to match what it hit so that it looks "plastered on"? I think a decal can do this but (from what I'm reading, I haven't tried implementing this yet) decals only apply to walls, not floors or ceilings. I know the long by-hand way would be to determine what was hit and calculate the angles based on that, but is there any build-in function in ZScript for doing that?
HitLine
field of the trace results to determine the angle. I've never done this myself, but I think you need to use the following formula:let l = TargetLook.HitLine;
double angle = atan2(l.v1.p.y - l.v2.p.y, l.v1.p.x - l.v2.p.x)
HitLine
is not null, which may not always be the case. This will get you the angle of the line itself; you have to either add or subtract 90 degrees from it depending on which side was hit (field LineSide
of the trace results equals either Line.front
or Line.back
). I don't have the means to test these formulas now, so you will have to experiment a bit, or wait for someone else to clarify them.Sir Robin wrote:A question about functions:
I want to write a function that takes a value between 0.0 and 1.0 and converts it to chars 'A'..'Z'
Pseudocode looks like this:char(toInt(min(max(value,0.0),1.0)*25)+65)
First, does ZScript have a char type or do I just use 1-length strings?
int
for single-bit chars, e.g. int ch = "A"
. To convert them to a string, use String.format("%c", ch)
. ZScript code equivalent to your pseudocode would be: (int)(Clamp(value, 0.0, 1.0) * 25 + 65)
Sir Robin wrote:Second what are the function equivalents in ZScript? this page is currently blank, is there a better resource?
Sir Robin wrote:Finally, where can I get the world tick count?
Level.maptime
Sat Jan 22, 2022 2:42 pm
time
and maptime
? I seem to remember that a couple years ago Iron Lich's Whirlwind had level.time
in it to determine how often the victim is thrust, and now it's Level.maptime
.
Sat Jan 22, 2022 2:53 pm
Level.time
should have been called "hubtime". It is the number of ticks passed since the beginning of the current hub. Level.maptime
is the number of ticks passed since first entering the current map within the hub (i.e. exiting and re-entering the map will not reset maptime back to zero).
Sun Jan 23, 2022 2:51 am
Mon Jan 24, 2022 5:15 am
Player701 wrote:It probably has to do something with the way yourUW_CursorPuff
class is coded, so if you could post its code here, I might be able to tell you what's wrong with it.
Spoiler:
Player701 wrote:As for the pitch - do you really need to calculate it for your actor? I'm not sure it would have any visual effect... Though I think there is a way to do it, I can look it up if you want.
Player701 wrote:If I remember right, you have to useint
for single-bit chars, e.g.int ch = "A"
. To convert them to a string, useString.format("%c", ch)
. ZScript code equivalent to your pseudocode would be:(int)(Clamp(value, 0.0, 1.0) * 25 + 65)
Player701 wrote:There is really a lot of them, so if you're looking for anything specific, don't be afraid to ask.
Player701 wrote:Level.maptime