Target Tracker (please help!)

Dear @choiceofgamescommunity and @CJW (who is always good at bailing me out of trouble!)

I am trying to implement a target tracker… and have got this far… HOWEVER it is #attack command that I can’t for the life of me figure out how to work… All I want to do is remove 1 measly hit point from whatever target is selected… but giving me the flexibility to have many different targets in the future (rather than hard coding every one separately)

I feel that I’m close but… nope can’t do it! So any help will be most appreciated! (code ought to cut and paste into a blank text file)


*temp n 1

*temp target_sel ""
*temp target_cur ""
*temp damage_cur 0
*temp hp_cur 0

*temp target_1 "pirate one"
*temp d_1 "d1"
*temp hits_1 3
*temp damage_1 10

*temp target_2 "pirate two"
*temp d_2 "d2"
*temp hits_2 4
*temp damage_2 20

*label start

*set target_cur {"target_"&n}
*set target_sel {"d_"&n}
*set damage_cur {"damage_"&n}
*set hp_cur {"hits_"&n}

target name = ${target_cur}
*line_break
target selected = ${target_sel}
*line_break
target damage = ${damage_cur} per hit
*line_break
target hit points = ${hp_cur}

*choice
 #cycle through targets
  *if target_sel = "d1"
   *set n 2
   *goto start
  *if target_sel = "d2"
   *set n 1
   *goto start
 #attack ${target_cur}
  *set hp_cur {("hits_"&n)} -1
  *goto start


(edit - trying to make it all make sense - as usual!)

Like so?


 #attack ${target_cur}
  *setref ("hits_"&n) (hp_cur - 1)
  *goto start

yes Yes YES!

Now why does it work…?!

I must say looking at your previous help for me I played at using *setref’s but to no avail… *scratch* will continue to ponder!

Brilliant stuff as ever (although easy for you no doubt!)

*set a variable by name
*set(a variable by)reference

So if we want to set something dynamically by a reference as opposed to a direct name we always use *setref.

Our reference is the string “hits_” AND the value of the variable n.
So… hits_1, hits_2 - Whichever one it is, that is the variable that gets modified.

Does that help?

@CJW hmm - is that why it didn’t like setting it directly… something about not starting with a letter… because it was subtracting from with a " " as opposed to subtracting from a variable directly?

Variables can’t contain “” - so the error was basically saying, ‘that’s definitely not a variable name you’re giving me there’, because of course, *set only accepts variable names.

*setref on the other hand allows you to use strings and variable values to ‘build’ or ‘reference’ a variable name.

If you haven’t already, check this out, the examples should make it much clearer:

Ah

#attack ${target_cur}
*set hp_cur -1
*goto start

So… the above on its own doesn’t work because although (hp_cur -1) is ok… you still need the set ref to assign the new value of (hp_cur -1) to override whatever the value of (“hits_”&n) was… I *think* that explanation makes sense no?

So I *was* close (ish) with

*set hp_cur {(“hits_”&n)} -1

Just a bit back to front (and wayward with the curly brackets… not sure why I added them but there were present in the other code and thought they were needed here too!)

{} references the value of something.
So yes, you were simply back to front, you were setting hp_cur to the value of the enemy in questions health (-1) as opposed to setting the enemy’s health to hp_cur (-1) :wink:

Cool - you’ll make an inveterate hacker out of me yet! Now adding 2 extra baddies once the first ones go…


*temp n 1

*temp target_sel ""
*temp target_cur ""
*temp damage_cur 0
*temp hp_cur 0

*temp target_1 "pirate one"
*temp d_1 "d1"
*temp hits_1 1
*temp damage_1 10

*temp target_2 "pirate two"
*temp d_2 "d2"
*temp hits_2 2
*temp damage_2 20

*label start
TARGETING TESTER

*set target_cur {"target_"&n}
*set target_sel {"d_"&n}
*set damage_cur {"damage_"&n}
*set hp_cur {"hits_"&n}

target name = ${target_cur}
*line_break
target selected = ${target_sel}
*line_break
target damage = ${damage_cur} per hit
*line_break
target hit points = ${hp_cur}

*choice
 #cycle through targets
  *if target_sel = "d1"
   *set n 2
   *goto start
  *if target_sel = "d2"
   *set n 1
   *goto start
 #attack ${target_cur}
  *setref ("hits_"&n) (hp_cur - 1)
  *gosub damcheck
  *goto start
   
*label damcheck
*if hits_1 = 0
 BOOM
 *temp target_1 "pirate three"
 *temp d_1 "d1"
 *temp hits_1 3
 *temp damage_1 30
 *goto start
*if hits_2 = 0
 BOOM
 *temp target_2 "pirate four"
 *temp d_2 "d2"
 *temp hits_2 4
 *temp damage_2 40
 *goto start
*return


It’s a sloppy work around - (and to complete I’d add options for when hits_3 and hits_4 = 0 in order to finish the battle) but…

I’d *like* to be able to set the n to 3 or 4 depending on whether they exist (only once either 1 or 2 have been dispatched) so might have 1 4 or 2 3 in play - depending on who got killed when. Now I can do the “check which two out of four exist routine” with lots of ifs ands and ors… this is ok… BUT - I’m overriding d_1 and d_2… is there a neater solution of setting n as 3 or 4? or is it just the ifs/ands/ors and lots of (()) routines…

I’m not quite sure what you mean, but you probably want to define every enemy separately?

What you’re essentially doing is simulating arrays or objects, CS supports neither, so this is about as good as it gets.

I’d actually edit your names so it’s more like:


*temp enemy_1 "pirate one"
*temp enemy_2_d "d2"
*temp enemy_2_health 4

Etc…

It’ll make the reference a little different/trickier, but it’ll make more sense when you come back to review your code at a later date, no?


*temp n 1

*temp target_sel ""
*temp target_cur ""
*temp damage_cur 0
*temp hp_cur 0

*temp target_1 "pirate one"
*temp d_1 "d1"
*temp hits_1 1
*temp damage_1 10

*temp target_2 "pirate two"
*temp d_2 "d2"
*temp hits_2 2
*temp damage_2 20

*temp target_3 "pirate three"
*temp d_3 "d3"
*temp hits_3 3
*temp damage_3 30

*temp target_4 "pirate four"
*temp d_4 "d4"
*temp hits_4 4
*temp damage_4 40

*label start
TARGETING TESTER

*set target_cur {"target_"&n}
*set target_sel {"d_"&n}
*set damage_cur {"damage_"&n}
*set hp_cur {"hits_"&n}

target name = ${target_cur}
*line_break
target selected = ${target_sel}
*line_break
target damage = ${damage_cur} per hit
*line_break
target hit points = ${hp_cur}

*choice
 #cycle through targets
  *if (target_sel = "d1") and (hits_2 > 0)
   *set n 2
   *goto start
  *if (target_sel = "d1") and ((hits_2 = 0) and (hits_3 > 0))
   *set n 3
   *goto start
  *if (target_sel = "d1") and ((hits_2 = 0) and (hits_3 = 0))
   *set n 4
   *goto start
  *if target_sel = "d2"
   *set n 1
   *goto start
  *if target_sel = "d3"
   *set n 1
   *goto start
  *if target_sel = "d4"
   *set n 1
   *goto start
 #attack ${target_cur}
  *setref ("hits_"&n) (hp_cur - 1)
  *gosub damcheck
  *goto start
   
*label damcheck
*if hits_1 = 0
 BOOM ONE DOWN
*if hits_2 = 0
 BOOM TWO DOWN
*if hits_3 = 0
 BOOM THREE DOWN
*if hits_4 = 0
 BOOM FOUR DOWN
*return


It isn’t complete but doesn’t fall down as long as you don’t kill off 1 (and needs tidying up too with the BOOMS)

Just wondering if there is a neater way of adjusting the *set n 1or2or3or4 when you “cycle through targets” depending on which pirates are in play - without the whole bunch of *if clauses that I gotta go through for all four of them. (I mean what if there were 100 pirates to go through - and only any 2 of them would be in play at once! @-) )

Oh, right - yeah.
Try giving each pirate a new property variable along the lines of “isinplay_1” make it a boolean, true or false.

Then when you #cycle, have a loop (refer to our sorting algorithm) that checks whether {“isinplay”&n} is equal to true, if it is - stop - use n’s stats ?

That’s a basic idea at any rate, I don’t have the time to write it for you right now.
But yeah, cycle through them all. Whilst it’s not what I’d call efficient (but if we cared about that level of practicality we wouldn’t use CS…), it’ll work and it’ll most certainly trim your code down!

Aha - thats what I’m talking about!

Dude that’s cool - wasn’t expecting you to write it - a point in the right direction is fine… I may just tailor the story to fit rather than try to make the code do anything as you say CS isn’t as slick as it could be… but it’s nice to have the option. I will have a play at some point and you can giggle at my efforts!

I want to be careful how I word it… You can actually do a surprising amount of stuff with CS, and anything you can’t you can always code in, or around with JavaScript. It’s just that *arguably* the only reason to use CS (over raw js) is to take advantage of its simplicity and tailoring. After all it’s largely aimed at authors who don’t know how to program.
Having said that, I highly doubt I’ll ever giggle at your efforts, it’s always nice to see people pushing the language, their games and themselves.

The language will also grow with time, I know they have a lot of useful features and improvements planned. It just takes time to implement them.

What I was getting at before was basically saying that yes, CS isn’t the most powerful, flexible or efficient way to create a game. But it’s easy, it’s fun and it works - so we don’t need to worry *too* much about being “efficient”.

Looping through a hundred bad guys every time you make a choice sounds like a lot, but to modern computers and browsers, it’s child’s play :slight_smile:

There is a system I coded in choice script to handle records in the fake array format. I got up to about 1,000 entries before I started noticing considerable performance issues.

To cut a long story short: if you want to experiment and do complicated stuff in choice script, go for it! I for one would love to see it :wink:

Agreed - that’s why I like CS - I think it is incredibly powerful for the “limited” number of commands that there are… I have no code-fu whatsoever… and yet I can remember how to do most of what is generally needed to code a CYOA game… and the options are seemingly limitless! (whether I can make them happen however is where you come in!)