Damage handling, targeting, move patterns and changing other units' variables

Started by Xindaris, October 15, 2013, 11:45:50 PM

Previous topic - Next topic

Xindaris

Some issues for making mostly the same unit in a map I'm working on, but useful things for me to learn about in general:

-Damage/targeting: If I want a unit to behave something like a drone in CW2, taking damage from cannons, snipers and maybe also mortars and AC, how do I make it "targetable" by all of those units (I know how to make it targetable by snipers, but that's about it)? And possibly more importantly, if I want this unit to be able to take more than one hit to kill, is there some way I can mimic runner damage-handling behavior for it? I looked around in the reference and couldn't find anything like "target" or "damage". In a similar vein, how do I make a CRPL Core take more than one nullifier hit to die?

-Special movement pattern: I want to have a unit that moves across a void track, but never goes "backwards" to where it originally came from. My idea at the moment is to have functions for moving east, north, south and west and putting another, invisible unit at each "intersection" that tells any of the moving units on top of it to go in one of the "correct" directions..but I'm not sure exactly how to do that. If I can make the "intersection" unit change a simple variable indicating the direction of the moving unit's movement, that would do it, but still need a different script for almost every intersection. The trouble is that there are many different kinds of intersections, so to keep all the variable handling in the moving unit I would have to have a way to distinguish between all the kinds of intersections and corners there are, and that sounds to me like a volume of code so massive and inefficient that there must be some better way to do it. I suppose I could instead make it so that it ran along a terrain track and never went "uphill", but I don't want the player to be able to "cheat" and alter the path with terps, either.

pawel345

As for health check the GetUnitAttribute and SetUnitAttribute it's there. CONST_HEALTH, CONST_MAXHEALTH and so on, the sniper does 20 damage per shot.

Hunter Seeker

Aspire to Inspire

Xindaris

Right. The problem with the terrain walker is that it picks where to go randomly at intersections. In particular it won't discriminate between going "forward" and going "backwards". I suppose I could try and change the way it decides whether or not an adjacent cell is valid to include whether or not there's another kind of CRPL unit standing on said place. To that end, is UID unique to each unit, or each unit type? Is there some way to give a unit some variable they hold onto that another unit can read? I'm thinking of making a unit have a string saying which ways it disallows the unit standing on it to go, for example $DONTGO:"north". Otherwise, I suppose I could make a bunch of more oblique numerical indicators of which directions the unit isn't allowed to go. Like 1=north, 5=north+east, 7=north + south, etc.

eduran

Quote from: Xindaris on October 16, 2013, 11:53:19 AM
is UID unique to each unit, or each unit type?
It's unique to each unit.

Quote from: Xindaris on October 16, 2013, 11:53:19 AM
Is there some way to give a unit some variable they hold onto that another unit can read?
GetScriptVar does that.

I am having a hard time understanding what your units are supposed to do, exactly. Wander about randomly on void but not go back to the cell from where they just came from? Or are they following some kind of maze?

Xindaris

Okay, I'll try to be more clear. There are two points, an origin and an endpoint, and a (very easy) maze between those two points. I want these units to navigate the maze starting at the origin and going to the endpoint, choosing randomly when both directions won't lead "backwards" on the maze. By "very easy", I mean that there are no dead ends and that at every intersection I know which directions are "backwards" just by glancing at it.

Okay, thank you. GetScriptVar should do exactly what I need done.

EDIT:
Okay, this isn't working, I can't figure out what's wrong, and I don't know how to look at the trace log the Trace function outputs to. So, this is my attempt at a making things do what I want them to:
# Intersection.crpl
# Created on: 10/16/2013 3:38:06 PM
# ------------------------------------------
#The only purpose of this script is to store a single variable.
#The variable tells mazemove units where they can't go. 1 = North, 2 = East,
# 3 = 1 + 2 = North + East, 4 = West, 5 = 1 + 4 = North + West, 6 = 2 + 4 = East + West,
# 7 = 1 + 2 + 4 = North + East + West, 8 = South, 9 = 1 + 8 = North + South,
# 10 = 2 + 8 = East + South, 11 = 1 + 2 + 8 = North + East + South, 12 = 4 + 8 = West + South,
# 13 = 1 + 4 + 8 = North + West + South, 14 = 2 + 4 + 8 = East + West + South.
$Forbidden:0


# Attacker.crpl
# Created on: 10/16/2013 3:22:17 PM
# ------------------------------------------
$direction:"north"
$speed:10

-1 -1 ->destX ->destY
0 ->forbidden

if (<-destX neq(CurrentX) <-destY neq(CurrentY) or) @SetDestination <-destX <-destY <-speed QueueMove endif

CurrentCoords 0 GetEnemyUnitsInRange ->unitCount
if(<-unitCount neq0)
while(<-unitCount neq0)
repeat
->currUnit
if(<-currUnit neq(Self) "Intersection" "forbidden" GetScriptVar neq(0) and)
<-currUnit "Intersection" "forbidden" GetScriptVar ->forbidden
@PickDirection
endif
<-unitCount sub(1) ->unitCount
endwhile
endif

:SetDestination
if(<-direction eq("east"))
CurrentX add(1) ->destX currentY ->destY
endif

if(<-direction eq("west"))
CurrentX sub(1) ->destX currentY ->destY
endif

if(<-direction eq("north"))
CurrentX ->destX CurrentY sub(1) ->destY
endif

if(<-direction eq("south"))
CurrentX ->destX CurrentY add(1) ->destY
endif

:PickDirection
"none" "none" "none" "none" ->dirArr1 ->dirArr2 ->dirArr3 ->dirArr4
0 ->dirArrSize

if(<-forbidden neq(1) <-forbidden neq(3) <-forbidden neq(5) <-forbidden neq(7) <-forbidden neq(9) <-forbidden neq(11) <-forbidden neq(13) and and and and and and)
"north" ->dirArr1
<-dirArrSize add(1) ->dirArrSize
endif

if(<-forbidden neq(2) <-forbidden neq(3) <-forbidden neq(6) <-forbidden neq(7) <-forbidden neq(10) <-forbidden neq(11) <-forbidden neq(14) and and and and and and)
if(<-dirArrSize eq(0)) "east" ->dirArr1
else "east" ->dirArr2
endif
<-dirArrSize add(1) ->dirArrSize
endif

if(<-forbidden neq(4) <-forbidden neq(5) <-forbidden neq(6) <-forbidden neq(7) <-forbidden neq(12) <-forbidden neq(13) <-forbidden neq(14) and and and and and and)
if(<-dirArrSize eq(0)) "west" ->dirArr1
else if(<-dirArrSize eq(1)) "west" ->dirArr2
else "west" ->dirArr3
endif endif
<-dirArrSize add(1) ->dirArrSize
endif

if(<-forbidden gte(8) not)
if(<-dirArrSize eq(0)) "south" ->dirArr1
else if(<-dirArrSize eq(1)) "south" ->dirArr2
else if(<-dirArrSize eq(2)) "south" ->dirArr3
else "south" ->dirArr4
endif endif endif
<-dirArrSize sub(1) ->dirArrSize
endif

1 <-dirArrSize RandInt ->dirPicker

if(<-dirPicker eq(1)) <-dirArr1 ->direction
else if(<-dirPicker eq(2)) <-dirArr2 ->direction
else if(<-dirPicker eq(3)) <-dirArr3 ->direction
else <-dirArr4 ->direction endif endif endif


I've tried moving around the @PickDirection command, which originally was placed right before the endif of that block it shows up in. I think that's the function that's bugged, but I have no idea what its problem could be. Otherwise, the issue is that it's getting a unit variable from a unit that isn't there and I have no idea what numbers it's coming up with, but it has a tendency to either keep going in the default direction or veer north after one step. It also does this weird thing where it'll take one step, pause, and then take another step, when what I want is "continuous" movement. The pauses seem to get longer or more frequent after the first few steps, too.

eduran

0) debugging commands. You put ShowTraceLog into a once block at the start of your script and use Trace(<-var) to add the value of var to the log.

1) You reset both forbidden and destX/Y at the start of your script. I think you want to put that into a once/endonce block. Otherwise your first if statement doesn't make any sense, because destX/Y is always -1 at that point. In case you want to check whether you are still moving or not you could use
if (not(GetQueuedMoveCount))

2) You have to remove the parentheses  between while and repeat. Repeat is the command that pops an item from the stack, not while:
while <-unitCount neq0 repeat
#or
while repeat(<-unitCount neq0)


3) Script names for Get/SetScriptVar have to include ".crpl"

4) The GetScriptVar command inside the if statement on line 17 is missing the unitUID

That's what the script looks like with these changes:


# Attacker.crpl
# Created on: 10/16/2013 3:22:17 PM
# ------------------------------------------
$direction:"north"
$speed:10
$debug:1

once
if(<-debug)
ShowTraceLog
ClearTraceLog
else
HideTraceLog
endif
-1 -1 ->destX ->destY
0 ->forbidden
endonce

if (not(GetQueuedMoveCount)) @SetDestination <-destX <-destY <-speed QueueMove endif

CurrentCoords 0 GetEnemyUnitsInRange ->unitCount
if(<-unitCount neq0)
while <-unitCount neq0
repeat
->currUnit
if(<-currUnit neq(Self) and (<-currUnit "Intersection.crpl" "Forbidden" GetScriptVar neq0) )
<-currUnit "Intersection.crpl" "Forbidden" GetScriptVar ->forbidden
@PickDirection
endif
<-unitCount sub(1) ->unitCount
endwhile
endif

:SetDestination
if(<-direction eq("east"))
CurrentX add(1) ->destX currentY ->destY
endif

if(<-direction eq("west"))
CurrentX sub(1) ->destX currentY ->destY
endif

if(<-direction eq("north"))
CurrentX ->destX CurrentY sub(1) ->destY
endif

if(<-direction eq("south"))
CurrentX ->destX CurrentY add(1) ->destY
endif

:PickDirection
"none" "none" "none" "none" ->dirArr1 ->dirArr2 ->dirArr3 ->dirArr4
0 ->dirArrSize

if(<-forbidden neq(1) <-forbidden neq(3) <-forbidden neq(5) <-forbidden neq(7) <-forbidden neq(9) <-forbidden neq(11) <-forbidden neq(13) and and and and and and)
"north" ->dirArr1
<-dirArrSize add(1) ->dirArrSize
endif

if(<-forbidden neq(2) <-forbidden neq(3) <-forbidden neq(6) <-forbidden neq(7) <-forbidden neq(10) <-forbidden neq(11) <-forbidden neq(14) and and and and and and)
if(<-dirArrSize eq(0)) "east" ->dirArr1
else "east" ->dirArr2
endif
<-dirArrSize add(1) ->dirArrSize
endif

if(<-forbidden neq(4) <-forbidden neq(5) <-forbidden neq(6) <-forbidden neq(7) <-forbidden neq(12) <-forbidden neq(13) <-forbidden neq(14) and and and and and and)
if(<-dirArrSize eq(0)) "west" ->dirArr1
else if(<-dirArrSize eq(1)) "west" ->dirArr2
else "west" ->dirArr3
endif endif
<-dirArrSize add(1) ->dirArrSize
endif

if(<-forbidden gte(8) not)
if(<-dirArrSize eq(0)) "south" ->dirArr1
else if(<-dirArrSize eq(1)) "south" ->dirArr2
else if(<-dirArrSize eq(2)) "south" ->dirArr3
else "south" ->dirArr4
endif endif endif
<-dirArrSize sub(1) ->dirArrSize
endif

1 <-dirArrSize RandInt ->dirPicker

if(<-dirPicker eq(1)) <-dirArr1 ->direction
else if(<-dirPicker eq(2)) <-dirArr2 ->direction
else if(<-dirPicker eq(3)) <-dirArr3 ->direction
else <-dirArr4 ->direction endif endif endif


Personally, I use warp notation almost exclusively. Sorry for the messy mix in styles.

Xindaris

It's fine; my notation is kind of back and forth on whether to warp certain things anyway. And I went and put in the suggested fixes manually to make sure I understood them. I also went and repaired some other bugs (like subtracting from the array size instead of adding, and the movement picking a spot 5 away instead of 1 away, something that was supposed to only be a temporary edit to check on something anyway) using the trace to find them. Then I found out that the final problem, which has been hounding me all along, was miscapitalizing the variable name "Forbidden". Now it looks like it should work exactly as intended. Thank you.