Creating Object Lists

My thread went dead on this subject and I am back at it.
Trying to create game.Orcs list and goblins and humans as well.
Any ideas why this function wont work in start.

Orcs = NewObjectList()
Goblins = NewObjectList()
Humans = NewObjectList()
Listofnpcs = FilterByType(AllObjects(), "monster")
foreach (object, Listofnpcs) {
  if (object.race = "Orc") {
    list add (Orcs, object)
  }
  else if (object.race = "Goblin") {
    list add (Goblins, object)
  }
  else if (race = "Human") {
    list add (Humans, object)
  }
}
game.Orcs = Orcs
game.Goblins = Goblins
game.Humans = Humans

Tried it with pre-made attributes and not. Either way the lists are always empty in debugger


K.V.

That last else if says race when I think it should be object.race.

Besides that, it seems to work for me.

Drop this into a new game and check the Log and Debugger out:

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Typewriter JS">
    <gameid>cb4bf0de-4de3-4e95-bb06-d9c53a16528a</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <start type="script">
      Orcs = NewObjectList()
      Goblins = NewObjectList()
      Humans = NewObjectList()
      Listofnpcs = FilterByType(AllObjects(), "monster")
      foreach (object, Listofnpcs) {
        if (object.race = "Orc") {
          list add (Orcs, object)
          // Debugging:
          Log (object +" is an Orc.")
        }
        else if (object.race = "Goblin") {
          list add (Goblins, object)
          // Debugging:
          Log (object +" is a Goblin.")
        }
        else if (object.race = "Human") {
          list add (Humans, object)
          // Debugging:
          Log (object +" is a Human.")
        }
        else {
          // Debugging:
          Log (object + " is not Orc, Goblin, or Human.")
        }
      }
      // Debugging:
      foreach (obj, ListExclude(AllObjects(),Listofnpcs)) {
        // Debugging:
        Log (obj +" does not have the type: 'monster'.")
      }
      game.Orcs = Orcs
      game.Goblins = Goblins
      game.Humans = Humans
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <beforeenter type="script">
    </beforeenter>
    <enter type="script">
    </enter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="Morcrest">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <race>Orc</race>
    </object>
    <object name="Vilhelm">
      <inherit name="editor_object" />
      <race>Human</race>
    </object>
    <object name="Schmeck">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <race>Goblin</race>
    </object>
    <object name="Ralph">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
    </object>
    <object name="Beetlejuice">
      <inherit name="editor_object" />
      <inherit name="monster" />
    </object>
    <object name="George">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <race>Human</race>
    </object>
  </object>
  <type name="monster" />
</asl>

1/13/2018 5:20:35 PM Object: Morcrest is an Orc.

1/13/2018 5:20:35 PM Object: Schmeck is a Goblin.

1/13/2018 5:20:35 PM Object: Beetlejuice is not Orc, Goblin, or Human.

1/13/2018 5:20:35 PM Object: George is a Human.

1/13/2018 5:20:35 PM Object: room does not have the type: 'monster'.

1/13/2018 5:20:35 PM Object: player does not have the type: 'monster'.

1/13/2018 5:20:35 PM Object: Vilhelm does not have the type: 'monster'.

1/13/2018 5:20:35 PM Object: Ralph does not have the type: 'monster'.


Edited code since first posting!


I have the script as a function and call it in the start script. Wonder if that screws it up?

Orc is not a type it is a value of an attribute named race.


K.V.

No, sir.

Just tested it.

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="NPC Races">
    <gameid>cb4bf0de-4de3-4e95-bb06-d9c53a16528a</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <start type="script">
      FindRaces
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <beforeenter type="script">
    </beforeenter>
    <enter type="script">
    </enter>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="Morcrest">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <race>Orc</race>
    </object>
    <object name="Vilhelm">
      <inherit name="editor_object" />
      <race>Human</race>
    </object>
    <object name="Schmeck">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <race>Goblin</race>
    </object>
    <object name="Ralph">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
    </object>
    <object name="Beetlejuice">
      <inherit name="editor_object" />
      <inherit name="monster" />
    </object>
    <object name="George">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <race>Human</race>
    </object>
  </object>
  <type name="monster" />
  <function name="FindRaces">
    Orcs = NewObjectList()
    Goblins = NewObjectList()
    Humans = NewObjectList()
    Listofnpcs = FilterByType(AllObjects(), "monster")
    foreach (object, Listofnpcs) {
      if (object.race = "Orc") {
        list add (Orcs, object)
        // Debugging:
        Log (object +" is an Orc.")
      }
      else if (object.race = "Goblin") {
        list add (Goblins, object)
        // Debugging:
        Log (object +" is a Goblin.")
      }
      else if (object.race = "Human") {
        list add (Humans, object)
        // Debugging:
        Log (object +" is a Human.")
      }
      else {
        // Debugging:
        Log (object + " is not Orc, Goblin, or Human.")
      }
    }
    // Debugging:
    foreach (obj, ListExclude(AllObjects(),Listofnpcs)) {
      // Debugging:
      Log (obj +" does not have the type: 'monster'.")
    }
    game.Orcs = Orcs
    game.Goblins = Goblins
    game.Humans = Humans
  </function>
</asl>

1/13/2018 5:29:07 PM Object: Morcrest is an Orc.
1/13/2018 5:29:07 PM Object: Schmeck is a Goblin.
1/13/2018 5:29:07 PM Object: Beetlejuice is not Orc, Goblin, or Human.
1/13/2018 5:29:07 PM Object: George is a Human.
1/13/2018 5:29:07 PM Object: room does not have the type: 'monster'.
1/13/2018 5:29:07 PM Object: player does not have the type: 'monster'.
1/13/2018 5:29:07 PM Object: Vilhelm does not have the type: 'monster'.
1/13/2018 5:29:07 PM Object: Ralph does not have the type: 'monster'.


K.V.

Try plugging my FindRaces() function into the game, then calling it from the start script, too.

Then check your Log and Debugger.

That function should work with what you've already got, and it should tell you why each object is or isn't added to a list.


Orc is not a type it is a value of an attribute named race.


K.V.

Orc is not a type it is a value of an attribute named race.

Precisely.

"monster" is the type.

the race attribute has three possibilities: Orc, Goblin, or Human. (It is a string attribute.)


Damn, I thought I was bored.


K.V.

Nein!

When it comes to the boredom, you know nuzzink!

(Sorry. I've been watching Hogan's Heroes.)


Shuuultz!


The log shows your function working but none of the game.lists are there in the debugger


It is not creating game.lists


K.V.

Hmm...

Velly intelesting...

It vorks for me:
image


Ok I'll investgate further. Ive didded something wrong


OMG. Had added parameters to the function and call in start.
Working now


Actually that was the old function. Yours was working when I called it. I was so used to seeing the attributes in a certain spot in game attributes because I manually added them before. The new ones were at the bottom after I removed the old ones. Duh


K.V.

You should marvel at some of my mistakes along with me some time.

It will be fun.

(B.Y.O.B.)


This should work too:

game.Orcs = FilterByAttribute(AllObjects(), "race", "Orc")

Pixie, I saw that in another thread and used it early on. I kept changing my script over and over because I couldn't get it to work. I started to think that I could not save or add directly to a game.list. That I had to make a NewObjectList, add to that and then newObjectList = game.list to create it. I see that isn't so.

When your code is used and the next line is foreach (item, orcs), I learned that i, j ,k are customary letters to use as the iterator variable ,but can I use anyword or letters for it? As long as those same letters are used in the script from then on?


Anyway, on to my next head scratcher. I saved each type of monster in a list then save those lists in a list called NPC. When a monster is attacked I want to make all ors or goblin or whatever attack the player on sight. I used the "mean" and kind just for identifiers (which I may not need.) I tried changing the attack on sight on all orcs and tried do( object, "attack" , put them in attacker list, all to no avail. I have read many threads but have not found any code that worked for me. It may have been the way to do it but I was unable to reword my code using the given code. It is the last lines that are trouble here. Plus the object.mode = "Mean" never changes when looking in the debugger.

 </function>
  <function name="ChangeHostility">
    foreach (object, game.NPC) {
      if (object.mode = "Mean") {
        object.mode = "Kind"
        list add (game.friends, "object")
        list remove (game.attackers, "object")
      }
      if (object.mode = "Kind" ) {
        object.mode = "Mean"
        object.attackonsight = "True"
      }
    }
  </function>

K.V.

Are game.friends and game.attackers both object lists?

If yes, I think these two lines should be like this (sans quotation marks):

        list add (game.friends, object)
        list remove (game.attackers, object)

If they are string lists, I think they should be:

        list add (game.friends, object.name)
        list remove (game.attackers, object.name)

If you add "object" to a string list, that just adds the string "object" to said string list. (I believe it should throw an error when trying to add a string to an object list (and vice-versa), by the way.) You probably want the local variable object.


I also think this line should not have quotation marks (making it a Boolean rather than a string):

object.attackonsight = true

Also, I don't see where you are modifying the game.attackers and game.friends lists when switching from "Kind" to "Mean".


EDIT

It also looks to me like you need that second if to be an else if.

Otherwise, I think it would change "Kind" to "Mean", no matter what.

...because, if it starts off as "Kind", the first if ignores it. Then, the second if changes "Kind" to "Mean".

If it starts off as "Mean", the first if will change it to "Kind", but the second if will change it right back to "Mean", because if(object.mode = "Kind") will return true at that point in the script.

So, it would always end up setting the attribute to "Mean" the way you posted it, unless you change that second if to else if.


So, it seems like this would work:

 <function name="ChangeHostility">
    foreach (object, game.NPC) {
      if (object.mode = "Mean") {
        object.mode = "Kind"
        list add (game.friends, object)
        list remove (game.attackers, object)
      }
      else if (object.mode = "Kind" ) {
        object.mode = "Mean"
        object.attackonsight = true
        list add (game.attackers, object)
        list remove (game.friends, object)
      }
    }
  </function>

K.V.

I learned that i, j ,k are customary letters to use as the iterator variable ,but can I use anyword or letters for it? As long as those same letters are used in the script from then on?

I believe this is true.

...just don't use e or pi. They exist already.

http://docs.textadventures.co.uk/quest/problems.html

‘e’ and ‘pi’

You will probably never need them in a text adventure, but e and pi are both mathematical constants. Quest will happily let you assign a value to them, but will ignore the assignment.


K.V.

I started to think that I could not save or add directly to a game.list. That I had to make a NewObjectList, add to that and then newObjectList = game.list to create it. I see that isn't so.

There are instances where you have to 'reset' a list.

I.e.,

You want to add an ENTER verb to an object's verb list.

(This may seem off-topic at first, but stick with me.)

First off, you can't create an ENTER verb because it is already a command, so you'd need to create an ENTER command (either in a specific room or for the entire game):

Command
Name: enter_cmd
Pattern: enter #object#

if (not HasAttribute(this, "enterable")) {
  msg ("You can't enter " + this.article + ".")
}
else {
  if (not this.enterable) {
    ("You can't enter " + this.article + ".")
  }
  else {
    MoveObject (game.pov, this)
  }
}

Then, we would add a Boolean attribute on any object we want the player to be able to enter, and we'd set it to true:

crate.enterable = true

Now that we've set all that up, let's add "Enter" to the crate's verb list to make things easier for the player.

(This assumes that we have NOT added any verbs at all to the crate object. That means crate.displayverbs has not been modified, and is an inherited list.)

This would NOT work:

list add (crate.displayverbs, "Enter")

Error running script: Cannot modify the contents of this list as it is defined by an inherited type. Clone it before attempting to modify.


This WOULD work, though:

crate.displayverbs = Split("Look at;Take;Enter", ";")

Alternatively, you could do this:

crate.displayverbs = NewStringList()
list add(crate.displayverbs, "Look at")
list add(crate.displayverbs, "Take")
list add(crate.displayverbs, "Enter")

Alternate 2:

// This first line creates a sort of clone of the list.  The two lists will not effect each other this way.
crate.displayverbsbackup = ListExclude(crate.displayverbs, "zzzz")
crate.displayverbs = NewStringList()
crate.displayverbs = crate.displayverbs + crate.displayverbsbackup
crate.displayverbs = crate.displayverbs + "Enter"
// This last line deletes the clone of the original list, which is no longer needed.
crate.displayverbsbackup = null

I think this works the same for inventoryverbs and generatedverbslist.


a String List holds String Values for its items:

(anything in double quotes is a String Value)

example_object.example_stringlist_attribute = NewStringList ()
list add (example_object.example_stringlist_attribute, "STRING_VALUE_1")
list add (example_object.example_stringlist_attribute, "STRING_VALUE_2")
list add (example_object.example_stringlist_attribute, "STRING_VALUE_3")

list add (example_object.example_stringlist_attribute, OBJECT_VALUE_1) // ERROR!!!!!


an Object List holds Object (reference/pointer) Values for its items:

(anything not in double quotes and not 'true/false', is an Object (reference/pointer) Value)

// create ("OBJECT_VALUE_1")
// create ("OBJECT_VALUE_2")
// create ("OBJECT_VALUE_3")

example_object.example_objectlist_attribute = NewObjectList ()
list add (example_object.example_objectlist_attribute, OBJECT_VALUE_1)
list add (example_object.example_objectlist_attribute, OBJECT_VALUE_2)
list add (example_object.example_objectlist_attribute, OBJECT_VALUE_3)

list add (example_object.example_objectlist_attribute, "STRING_VALUE_1") // ERROR!!!!!


foreach (NAME_OF_Variable, NAME_OF_OBJECT.NAME_OF_LIST_ATTRIBUTE) { /* scripting */ }

the 'NAME_OF_Variable' can be whatever you want, it's just a Variable


here's how 'foreach' works (conceptually):

create ("joe")
joe.run_laps => msg ("Joe runs laps")

create ("jim")
jim.run_laps => msg ("Jim runs laps")

create ("jeff")
jeff.run_laps => msg ("Jeff runs laps")

team_object.team_objectlist_attribute = NewObjectList ()
list add (team_object.team_objectlist_attribute, joe)
list add (team_object.team_objectlist_attribute, jim)
list add (team_object.team_objectlist_attribute, jeff)

foreach (team_member, team_object.team_objectlist_attribute) {
  do (team_member, "run_laps")
  //
  // team_member = joe
  // do (team_member, "run_laps")
  // do (joe, "run_laps")
  //
  // team_member = jim
  // do (team_member, "run_laps")
  // do (jim, "run_laps")
  //
  // team_member = jeff
  // do (team_member, "run_laps")
  // do (jeff, "run_laps")
}

// output:

Joe runs laps
Jim runs laps
Jeff runs laps

The problem is the actual list game.attacker does no make all orcs attack me. It is just for that parent room apparently. If I move to another room where another orc is, it does not attack. The attacker list only has the original orc I attacked. and "Kind" remains "Kind". The attackonsight remains False". The script may have no errors, but does nothing,

<function name="ChangeHostility">
    foreach (object, game.NPC) {
      if (object.mode = "Mean") {
        object.mode = "Kind"
        list add (game.friends, object)
        list remove (game.attackers, object)
      }
      else if (object.mode = "Kind" ) {
        object.mode = "Mean"
        object.attackonsight = true
        list add (game.attackers, object)
        list remove (game.friends, object)
      }
    }
  </function>

I learned that i, j ,k are customary letters to use as the iterator variable ,but can I use anyword or letters for it? As long as those same letters are used in the script from then on?

i, j and k are conventionally used if the iterator is an integer, i.e., for a for loop, not for a foreach loop. But you can use anything.

I saved each type of monster in a list then save those lists in a list called NPC.

So does game.NPC contain three eements, each one a list? Or is it the combination of the three lists?

There are instances where you have to 'reset' a list.

Specifically where the list belongs to the type, rather than the object. If your object uses the default verb list, then that verb list is on its type, not the object itself, and you cannot change it.

You can reset it, as you say, but anotherway is to add something to the list in the editor, and then remove it. This will ensure the object has ts own list.


I got theses to lines from Monster.xml in combat.lib.

list add (game.friends, object)
list remove (game.attackers, object)

They sound like they would work but don't. I need the line that triggers a monster to attack on sight. I thought that would be

 object.attackonsight = true

But attackonsight remains "false" using that line. It is inherited(grayed).
Changing it manually to true works. so that line in the script is not working.


So does game.NPC contain three eements, each one a list? Or is it the combination of the three lists?

I used

list add (game.NPC, Humans; Goblins; Orcs)

And i just checked and it remains empty. oops!
Can I use "+" here?*

game.NPC = Humans + Goblins + Orcs

Tried it but does not add the lists to NPC

I will try list add on each one separately.

list add (game.NPC, Orcs)
list add (game.NPC, Goblins)
list add (game.NPC, Humans)

Nope

list add (game.NPC, game.Orcs)
list add (game.NPC, game.Goblins)
list add (game.NPC, game.Humans)

Nope

list add (game.NPC, game.Orcs)
list add (game.NPC, game.Goblins)
list add (game.NPC, game.Humans)

Nope


K.V.

I saved each type of monster in a list then save those lists in a list called NPC. When a monster is attacked I want to make all ors or goblin or whatever attack the player on sight.

So, if one orc gets pissed off, you want all the orcs to be pissed off... (I need to slow down and read sometimes.)

It sounds like you want script something like:

  <function name="ChangeHostility" parameters="race">
    objectlist = FilterByAttribute(AllObjects(), "race", race)
    foreach (object, objectlist) {
      if (object.mode = "Mean") {
        object.mode = "Kind"
        list add (game.friends, object)
        list remove (game.attackers, object)
      }
      else if (object.mode = "Kind" ) {
        object.mode = "Mean"
        object.attackonsight = true
        list add (game.attackers, object)
        list remove (game.friends, object)
      }
    }
  </function>

Then, I have this in the attack script on the NPC:

msg("You attack "+GetDisplayName(this)+".")
// Do whatever here - kill the NPC, add damage, or a miss
ChangeHostility (this.race)

So, when I attack an Orc, all the Orcs are "Mean" and their "attackonsight" attributes are all true.


K.V.

Before attacking Morcrest (an orc):

image

image

image

After attacking Morcrest:

image

image

image


ooooh! Parameters....


K.V.

Adding this to the end of FindRaces() is one way you could make that game.NPC list work:

    game.NPC = NewList()
    list add(game.NPC, game.Orcs)
    list add(game.NPC, game.Goblins)
    list add(game.NPC, game.Humans)

image


K.V.

Oops!

I posted that twice, somehow!


I had added ChangeHostility to the attack script but in the GUI and put race as parameter not this.race. Had no parameters earlier

Used your script and ingame I attacked an orc...Went to another room and the orc there said "Sup"... no wait he attacked me..that Sum b.
Thanks so much!


K.V.

How will you retrieve from game.NPC, though?

It would be like:

lc = ListCount(game.NPC)
for (i, 0, lc-1) {
  foreach (obj, game.NPC[i]) {
    // Do whatever, like:
    msg (obj)
  }
}

Which would output:


Object: Morcrest
Object: Scar
Object: Schmeck
Object: George


...but you wouldn't know who was what, just that they were all "monster" types, which is how the lists are derived...


What do you do with game.NPC, game.Orcs, game.Goblins, and game.Humans besides the ChangeHostility() thing?

If you use those lists for other things, I recommend making game.NPC a dictionary.

  <function name="FindRaces">
    game.Orcs = FilterByAttribute(AllObjects(), "race", "Orc")
    game.Goblins = FilterByAttribute(AllObjects(), "race", "Goblin")
    game.Humans = FilterByAttribute(AllObjects(), "race", "Human")
    game.NPC = NewDictionary()
    dictionary add (game.NPC, "Orcs", game.Orcs)
    dictionary add (game.NPC, "Goblins", game.Goblins)
    dictionary add (game.NPC, "Humans", game.Humans)
  </function>

Then, you could do ChangeHostility() like this:

  <function name="ChangeHostility" parameters="race">
    // race will be "Orc", "Goblin", or "Human", but we have it set up so that each list name (or dictionary key) ends in an "s" (making them plural)
    // I left it this way in case your game has numerous scripts with this setup already
    race_type = race + "s"
    race_list = DictionaryItem(game.NPC,race_type)
    foreach (object, race_list) {
      if (object.mode = "Mean") {
        object.mode = "Kind"
        list add (game.friends, object)
        list remove (game.attackers, object)
      }
      else if (object.mode = "Kind" ) {
        object.mode = "Mean"
        object.attackonsight = true
        list add (game.attackers, object)
        list remove (game.friends, object)
      }
    }
  </function>

image


If you don't use all those lists anywhere else, you could probably do away with some (if not most) of them.


EDIT

Yay!

You got it working while I was typing this!

Whoo-hoo!


The script you gave me before did not require the NPC list. Which I had yet to get working.
This one will add the NPC for me. Again Thank you.

Nothing like being spoon fed...

I have a large game but am redoing it slowly, trying to get all the functions and basic scripts working before coping/pasting a lot of old content to the new code. So now is the time to figure it out.
Adding functions and different change scripts tend to screw thing up in a large game, when you don't know exactly what your doing. Sayin'


I used the "Mean" and Kind" as a simple way to determine in other scripts if the monster is going to attack . I could use code to determine if the monster is in the attacker list.

Even with your new code, I noticed in debugger, the Mean and Kind are not changing in the original attacked monster or the other like race monsters.

Any thoughts on that.

Wait, let me get my spoon...


Oh wait... I forgot to re-add the race list creation function to the start script...


  • I think the 'friends' is an attribute I added earlier to to work like 'mode'. It is not needed.
  • I may not need to add the monster to the attackers list. Just the attackonsight attribute being set to "true" may do it.
  • I wonder if Mode should be a type with a script that does what the ChangeHostility function does. Then add mode type to the Monster type...
  • I may make it so the same/race attacks are only effective in a general area. It's not like they have a telegraph system to tell other orcs (miles/kilometers/several days travel) away that the player needs a woopin'.

I'll look into this tomorrow. Gotta leave for work shortly. Those Walmart shelves aren't gonna straighten themselves! 3rd shift rules!


K.V.

Sorry, I nodded off. (I'm old.)


Adding functions and different change scripts tend to screw thing up in a large game

Change scripts?

Ooh, I hate it when change scripts throw errors!

It always takes me forever to even think of checking my change scripts.

I usually:

  • change all sorts of other scripts
  • change them back when that helps nothing
  • curse the gods of programming
  • curse myself
  • curse whoever is in my vicinity
  • rinse & repeat
  • give up for a while
  • THEN I think of checking out the change scripts!

I may make it so the same/race attacks are only effective in a general area.

[insert dramatic music here]

If you're just talking about the orcs in the same room, that would be very easy to implement.

Otherwise, do you have rooms inside of one room, the parent room being a "region"?

If yes, it probably wouldn't be that difficult. If not, we could probably come up with something (like iterating through the exits of the player's parent object and making an object list of each exit.to).


I wonder if Mode should be a type with a script that does what the ChangeHostility function does. Then add mode type to the Monster type...

What'chu talkin' 'bout, Willis?

(Seriously. Please expound upon this one. (I didn't nap long enough. Ha-ha!)


As far as all those attributes are concerned, I think you only need the one dictionary: game.NPC.

Here is my example game:

(NOTE: This has nothing to do with spoons. It's just easier for me when I can see the entire code, with all the scripts that work together. I assume everyone else is like me. (Right?))

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="example_game">
    <gameid>d821c1d9-fa44-4d24-9658-627812651b61</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <start type="script">
      FindRaces
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <feature_startscript />
      <attr name="_initialise_" type="script">
        game.pov.alias = "you"
      </attr>
    </object>
    <object name="Morcrest">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Orc</race>
      <mode>Kind</mode>
    </object>
    <object name="Vilhelm">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
      <race>Human</race>
    </object>
    <object name="Schmeck">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Goblin</race>
    </object>
    <object name="Ralph">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
    </object>
    <object name="Beetlejuice">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
    </object>
    <object name="George">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Human</race>
    </object>
    <object name="Scar">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Orc</race>
    </object>
  </object>
  <verb>
    <property>attack</property>
    <pattern>attack</pattern>
    <defaultexpression>"You can't attack " + object.article + "."</defaultexpression>
  </verb>
  <turnscript name="monsters_attack_turnscript">
    <enabled />
    <script>
      foreach (o, FilterByType(AllObjects(), "monster")) {
        if (o.attackonsight) {
          if (o.parent = game.pov.parent) {
            DoAttack (o, game.pov)
          }
        }
      }
    </script>
  </turnscript>
  <type name="monster">
    <attackonsight type="boolean">false</attackonsight>
    <attackscript type="script">
      DoAttack (this, game.pov)
    </attackscript>
    <attack type="script">
      msg ("You attack "+GetDisplayName(this)+".")
      // Do whatever here - kill or add damage - I'm just going to kill the NPC for simplicity's sake.
      msg (CapFirst(GetDisplayName(this))+" falls dead then fades away, as if this were some sort of video game.")
      RemoveObject (this)
      // END OF "kill or add damage"
      ChangeHostility (this.race)
    </attack>
    <feature_startscript />
    <attr name="_initialise_" type="script">
      this.displayverbs = Split("Look at;Speak to;Attack",";")
    </attr>
  </type>
  <function name="FindRaces">
    if (not HasAttribute(game, "NPC")) {
      game.NPC = NewDictionary()
    }
    dictionary add (game.NPC, "Orc", FilterByAttribute(AllObjects(), "race", "Orc"))
    dictionary add (game.NPC, "Goblin", FilterByAttribute(AllObjects(), "race", "Goblin"))
    dictionary add (game.NPC, "Human", FilterByAttribute(AllObjects(), "race", "Human"))
  </function>
  <function name="ChangeHostility" parameters="race">
    // I altered this so it only effects NPCs in the room when you attack.
    foreach (object, DictionaryItem(game.NPC, race)) {
      if(object.parent = game.pov.parent){
        if (object.attackonsight) {
          object.attackonsight = false
        }
        else {
          object.attackonsight = true
          msg (CapFirst(GetDisplayName(object))+" looks angry now!")
        }
      }
    }
  </function>
  <function name="DoAttack" parameters="attacker, target">
    msg (CapFirst(GetDisplayName(attacker))+" attacks "+GetDisplayName(target)+"!")
  </function>
</asl>

First things last:

Even with your new code, I noticed in debugger, the Mean and Kind are not changing in the original attacked monster or the other like race monsters.

You got this working; right?


K.V.

PS

You need to rotate stock and front those shelves, too, man!

You can't just straighten them...

(All K-Mart did was straighten, and look what happened to them!)


#InventoryJokes


  • Making the hostility change script part of the monster type would end having to add the function to attack command for each monster. Types can hold scripts too, so when the attack script is called, depending on the monster race different monsters can handle the attack differently. Maybe it will run away, maybe it will lead you to a bunch of his hidden buddies, maybe shat himself.
  • First things last...Oh wait... I forgot to re-add the race list creation function to the start script...
  • Entire scripts are just something I have to scroll past to get to the good stuff below it. Hey, I tell ya, I kid the feeble minded. That was Rodney Dangerfield. I do a great impression of him BTW. No Respect. I prefer the whole script too.
  • Boot the other attributes. Agree
  • I always have to rotate stock and front those shelves. we call it maize...no wait, zoning, we call it zoning.

The general area I was talking about was certain regions in the game. Mountains, or grasslands and the such. No reason to piss off the whole nation of orcs.


K.V.

Making the hostility change script part of the monster type would end having to add the function to attack command for each monster.

Mmm...

I think you'd still have to have at least one line which ran that ChangeHostility script, whether the script was a function, or a script attribute, or you just entered all the code directly into the script.


Types can hold scripts too, so when the attack script is called, depending on the monster race different monsters can handle the attack differently.

Sounds like you'd either:


A. need three new types to pull this off:

  • Orc
  • Goblin
  • Human

B. need to modify the monster_turnscript after making a few other adjustments. Paste this in place of the full code of a new game and attack Vilhelm, George, Morcrest, or Scar:


 <!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="example_game">
    <gameid>d821c1d9-fa44-4d24-9658-627812651b61</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <start type="script">
      FindRaces
      SetHostility
    </start>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <feature_startscript />
      <attr name="_initialise_" type="script">
        game.pov.alias = "you"
      </attr>
    </object>
    <object name="Morcrest">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Orc</race>
      <mode>Kind</mode>
    </object>
    <object name="Vilhelm">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
      <inherit name="monster" />
      <race>Human</race>
    </object>
    <object name="Schmeck">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Goblin</race>
    </object>
    <object name="Ralph">
      <inherit name="editor_object" />
      <inherit name="namedmale" />
      <fleeonsight />
    </object>
    <object name="Beetlejuice">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
    </object>
    <object name="George">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Human</race>
    </object>
    <object name="Scar">
      <inherit name="editor_object" />
      <inherit name="monster" />
      <inherit name="namedmale" />
      <race>Orc</race>
    </object>
    <exit alias="north" to="another room">
      <inherit name="northdirection" />
    </exit>
  </object>
  <verb>
    <property>attack</property>
    <pattern>attack</pattern>
    <defaultexpression>"You can't attack " + object.article + "."</defaultexpression>
  </verb>
  <turnscript name="monsters_turnscript">
    <enabled />
    <script>
      foreach (o, FilterByType(AllObjects(), "monster")) {
        if (o.parent = game.pov.parent) {
          if (o.attackonsight) {
            DoAttack (o, game.pov)
          }
          else if (o.fleeonsight) {
            o.exit = PickOneUnlockedExit (game.pov.parent)
            msg (CapFirst(GetDisplayName(o)) + " runs away to the {exit:"+o.exit.name+"}!")
            MoveObject (o, o.exit.to)
            o.exit = null
          }
        }
      }
    </script>
  </turnscript>
  <object name="another room">
    <inherit name="editor_room" />
    <exit alias="south" to="room">
      <inherit name="southdirection" />
    </exit>
  </object>
  <type name="monster">
    <attackonsight type="boolean">false</attackonsight>
    <feature_startscript />
    <fleeonsight type="boolean">false</fleeonsight>
    <attackscript type="script">
      DoAttack (this, game.pov)
    </attackscript>
    <attack type="script">
      msg ("You attack "+GetDisplayName(this)+".")
      // Do whatever here - kill or add damage - I'm just going to kill the NPC for simplicity's sake.
      msg (CapFirst(GetDisplayName(this))+" falls dead then fades away, as if this were some sort of video game.")
      RemoveObject (this)
      // END OF "kill or add damage"
      ChangeHostility (this.race)
    </attack>
    <attr name="_initialise_" type="script">
      this.displayverbs = Split("Look at;Speak to;Attack",";")
    </attr>
    <angers type="boolean">false</angers>
    <flees type="boolean">false</flees>
  </type>
  <function name="FindRaces">
    if (not HasAttribute(game, "NPC")) {
      game.NPC = NewDictionary()
    }
    dictionary add (game.NPC, "Orc", FilterByAttribute(AllObjects(), "race", "Orc"))
    dictionary add (game.NPC, "Goblin", FilterByAttribute(AllObjects(), "race", "Goblin"))
    dictionary add (game.NPC, "Human", FilterByAttribute(AllObjects(), "race", "Human"))
  </function>
  <function name="ChangeHostility" parameters="race">
    // I altered this so it only effects NPCs in the room when you attack.
    foreach (object, DictionaryItem(game.NPC, race)) {
      if (object.parent = game.pov.parent) {
        if (object.angers) {
          if (object.attackonsight) {
            object.attackonsight = false
          }
          else {
            object.attackonsight = true
            msg (CapFirst(GetDisplayName(object))+" looks angry now!")
          }
        }
        else if (object.flees) {
          if (object.fleeonsight) {
            object.fleeonsight = false
          }
          else {
            object.fleeonsight = true
            msg (CapFirst(GetDisplayName(object))+" looks frightened now!")
          }
        }
      }
    }
  </function>
  <function name="DoAttack" parameters="attacker, target">
    msg (CapFirst(GetDisplayName(attacker))+" attacks "+GetDisplayName(target)+"!")
  </function>
  <function name="SetHostility">
    foreach (orc, DictionaryItem(game.NPC,"Orc")) {
      orc.angers = true
    }
    foreach (goblin, DictionaryItem(game.NPC,"Goblin")) {
      goblin.angers = true
    }
    foreach (human, DictionaryItem(game.NPC,"Human")) {
      human.flees = true
    }
  </function>
</asl>

K.V.

Here it is with two regions.

The first two rooms are in one region, the third is in a region of its own.

So, attacking someone in room or another room will effect the NPCs in both of those rooms, but third room folks know nothing of the goings on anywhere besides in their room (unless an NPC is 'visiting' third room after fleeing there from the other region).

<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="example_game">
    <gameid>d821c1d9-fa44-4d24-9658-627812651b61</gameid>
    <version>1.0</version>
    <firstpublished>2018</firstpublished>
    <start type="script">
      FindRaces
      SetHostility
    </start>
  </game>
  <verb>
    <property>attack</property>
    <pattern>attack</pattern>
    <defaultexpression>"You can't attack " + object.article + "."</defaultexpression>
  </verb>
  <turnscript name="monsters_turnscript">
    <enabled />
    <script>
      foreach (o, FilterByType(AllObjects(), "monster")) {
        if (o.parent = game.pov.parent) {
          if (o.attackonsight) {
            DoAttack (o, game.pov)
          }
          else if (o.fleeonsight) {
            o.exit = PickOneUnlockedExit (o.parent)
            msg (CapFirst(GetDisplayName(o)) + " runs away to the {exit:"+o.exit.name+"}!")
            MoveObject (o, o.exit.to)
          }
        }
      }
    </script>
  </turnscript>
  <object name="northern_region">
    <inherit name="editor_room" />
    <object name="room">
      <inherit name="editor_room" />
      <object name="player">
        <inherit name="editor_object" />
        <inherit name="editor_player" />
        <usedefaultprefix type="boolean">false</usedefaultprefix>
        <feature_startscript />
        <attr name="_initialise_" type="script">
          game.pov.alias = "you"
        </attr>
      </object>
      <object name="Morcrest">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Orc</race>
        <mode>Kind</mode>
      </object>
      <object name="Vilhelm">
        <inherit name="editor_object" />
        <inherit name="namedmale" />
        <inherit name="monster" />
        <race>Human</race>
      </object>
      <object name="Schmeck">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Goblin</race>
      </object>
      <object name="Ralph">
        <inherit name="editor_object" />
        <inherit name="namedmale" />
        <fleeonsight />
      </object>
      <object name="Beetlejuice">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
      </object>
      <object name="George">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Human</race>
      </object>
      <object name="Scar">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Orc</race>
      </object>
      <exit alias="north" to="another room">
        <inherit name="northdirection" />
      </exit>
    </object>
    <object name="another room">
      <inherit name="editor_room" />
      <usedefaultprefix type="boolean">false</usedefaultprefix>
      <exit alias="south" to="room">
        <inherit name="southdirection" />
      </exit>
      <exit alias="north" to="third room">
        <inherit name="northdirection" />
      </exit>
      <object name="Wormface">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Orc</race>
      </object>
      <object name="Bill">
        <inherit name="editor_object" />
        <inherit name="namedmale" />
        <inherit name="monster" />
        <race>Human</race>
      </object>
      <object name="Knothead">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Goblin</race>
      </object>
      <object name="Tomas">
        <inherit name="editor_object" />
        <inherit name="namedmale" />
        <fleeonsight />
      </object>
      <object name="Fordo">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
      </object>
      <object name="Joe">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Human</race>
      </object>
    </object>
  </object>
  <object name="southern_region">
    <inherit name="editor_room" />
    <object name="third room">
      <inherit name="editor_room" />
      <object name="Rott">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Orc</race>
        <mode>Kind</mode>
      </object>
      <object name="William">
        <inherit name="editor_object" />
        <inherit name="namedmale" />
        <inherit name="monster" />
        <race>Human</race>
      </object>
      <object name="Schpleck">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Goblin</race>
      </object>
      <object name="Fred">
        <inherit name="editor_object" />
        <inherit name="namedmale" />
        <fleeonsight />
      </object>
      <object name="Beetelgeuse">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
      </object>
      <object name="Jorge">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Human</race>
      </object>
      <object name="Gasher">
        <inherit name="editor_object" />
        <inherit name="monster" />
        <inherit name="namedmale" />
        <race>Orc</race>
      </object>
      <exit alias="south" to="another room">
        <inherit name="southdirection" />
      </exit>
    </object>
  </object>
  <type name="monster">
    <attackonsight type="boolean">false</attackonsight>
    <feature_startscript />
    <fleeonsight type="boolean">false</fleeonsight>
    <angers type="boolean">false</angers>
    <flees type="boolean">false</flees>
    <attackscript type="script">
      DoAttack (this, game.pov)
    </attackscript>
    <attack type="script">
      msg ("You attack "+GetDisplayName(this)+".")
      // Do whatever here - kill or add damage - I'm just going to kill the NPC for simplicity's sake.
      msg (CapFirst(GetDisplayName(this))+" falls dead then fades away, as if this were some sort of video game.")
      RemoveObject (this)
      // END OF "kill or add damage"
      ChangeHostility (this.race)
    </attack>
    <attr name="_initialise_" type="script">
      this.displayverbs = Split("Look at;Speak to;Attack",";")
    </attr>
  </type>
  <function name="FindRaces">
    if (not HasAttribute(game, "NPC")) {
      game.NPC = NewDictionary()
    }
    dictionary add (game.NPC, "Orc", FilterByAttribute(AllObjects(), "race", "Orc"))
    dictionary add (game.NPC, "Goblin", FilterByAttribute(AllObjects(), "race", "Goblin"))
    dictionary add (game.NPC, "Human", FilterByAttribute(AllObjects(), "race", "Human"))
  </function>
  <function name="ChangeHostility" parameters="race">
    // I altered this so it only effects NPCs in the room when you attack.
    foreach (object, DictionaryItem(game.NPC, race)) {
      if (not object.parent = null) {
        if (object.parent.parent = game.pov.parent.parent) {
          if (object.angers) {
            if (object.attackonsight) {
              object.attackonsight = false
            }
            else {
              object.attackonsight = true
              if (object.parent = game.pov.parent) {
                msg (CapFirst(GetDisplayName(object))+" looks angry now!")
              }
            }
          }
          else if (object.flees) {
            if (object.fleeonsight) {
              object.fleeonsight = false
            }
            else {
              object.fleeonsight = true
              if (object.parent = game.pov.parent) {
                msg (CapFirst(GetDisplayName(object))+" looks frightened now!")
              }
            }
          }
        }
      }
    }
  </function>
  <function name="DoAttack" parameters="attacker, target">
    msg (CapFirst(GetDisplayName(attacker))+" attacks "+GetDisplayName(target)+"!")
  </function>
  <function name="SetHostility">
    foreach (orc, DictionaryItem(game.NPC,"Orc")) {
      orc.angers = true
    }
    foreach (goblin, DictionaryItem(game.NPC,"Goblin")) {
      goblin.angers = true
    }
    foreach (human, DictionaryItem(game.NPC,"Human")) {
      human.flees = true
    }
  </function>
</asl>

K.V.

This is fun.

What if, when an NPC flees, and they end up in a new region, you give the player a turn or two to run the NPC off, before he infects the NPCs of his race in the new region with his fears of you.

I figure the humans would be the ones to run. I also reckon the humans are the ones you need to speak to in order to gain information sometimes. So, if all of the humans run from you, you are screwed.

See where I'm going with that? Or do I have toys in the attic today? (Simply gone fishing.)


Holy crap!

I'm using some of this code in a fishing script!


Humans are always scared of this player character. It is a mythical creature. The player will need to discover a way to transform into a human form if he wants to defeat another evil bastard (who controls you). For now if you enter an area with humans they will mostly run, but there always seems to be one or two that will want to take a stab at you. That's the last of them...

You play a gargoyle. The cause of many crying widows and soiled cotton under garments. You are actually a pretty nice fella since being summoned from hell, away from your torturous job involving the damned. Humans just won't give ya a chance.


Imagine flying up in the sky. You've learned to follow the lay of the forests and avoid roads and clearing. Suddenly, you can see some humans out hunting and they just happen to be in a small clearing.

They've seen you! At first they are puzzled as to what they are actually seeing, but after a moment they begin to run into the shelter of the trees.

You quickly veer off to get out of their sight but it is too late. One of them carefully aims a bow into the air and lets loose an arrow. It flies by, just missing your head .

You turn back toward the attacker and dive straight for them. "Well", you think to yourself, "I haven't had mid-day meal yet!"


It's the typical medieval romp through the 1500's. Set in Bristol, England.


K.V.

That sounds cool!

Sign me up for beta-testing!


Bug Alert (Edited)

The ChangeHostility function adds the original monster that the player attacks to the list of attackers every time the player attacks during battle, so there are multiples of that monster in the attackers list giving it more and more attacks each turn. Which is kinda funny but not what we're after here.

The monster starts getting more attacks on the third attack.
First attack adds him to the list of attackers.
Second attack adds him the second time, so you would think he would get 2 attacks, but doesn't.
This leads me to believe he is added to the list after he attacks.
Third attack on him he get 2 attacks.

Plus this bug is causing my fancy hitpoint gauge to not work. its there just not lowering and I seem to battle passed the point of what should have triggered my death.

I will see if I can ListExclude somehow or I could flag him after first attack and reference that flag. Burning the midnight oil tonight...good thing it's my night off


K.V.

Are you using this one?

  <function name="ChangeHostility" parameters="race">
    // I altered this so it effects NPCs in the REGION when you attack.
    foreach (object, DictionaryItem(game.NPC, race)) {
      if (not object.parent = null) {
        if (object.parent.parent = game.pov.parent.parent) {
          if (object.angers) {
            if (object.attackonsight) {
              object.attackonsight = false
            }
            else {
              object.attackonsight = true
              if (object.parent = game.pov.parent) {
                msg (CapFirst(GetDisplayName(object))+" looks angry now!")
              }
            }
          }
          else if (object.flees) {
            if (object.fleeonsight) {
              object.fleeonsight = false
            }
            else {
              object.fleeonsight = true
              if (object.parent = game.pov.parent) {
                msg (CapFirst(GetDisplayName(object))+" looks frightened now!")
              }
            }
          }
        }
      }
    }
  </function>

No,

race_type = race + "s"
race_list = DictionaryItem(game.NPC,race_type)
foreach (object, race_list) {
  if (object.mode = "Mean") {
    object.mode = "Kind"
    list add (game.friends, object)
    list remove (game.attackers, object)
  }
  else if (object.mode = "Kind" ) {
    object.mode = "Mean"
    object.attackonsight = true
    list add (game.attackers, object)
    list remove (game.friends, object)
    if (HasAttribute(object, "attacked")) {
    }
  }
}

Was going to use a flag, but if I read the list of attackers each attack and exclude the ones there already, I should be good.


K.V.

REVISED

race_type = race + "s"
race_list = DictionaryItem(game.NPC,race_type)
foreach (object, race_list) {
  if (object.mode = "Mean") {
    object.mode = "Kind"
    if (not ListContains(game.friends, object){
      list add (game.friends, object)
    }
    if (ListContains(game.attackers, object)){
      list remove (game.attackers, object)
    }
  }
  else if (object.mode = "Kind" ) {
    object.mode = "Mean"
    object.attackonsight = true
    if (not ListContains(game.attackers, object){
      list add (game.attackers, object)
    }
    if (ListContains(game.friends, object)){
      list remove (game.friends, object)
    }
    if (HasAttribute(object, "attacked")) {
      // You have no script here.  (I'm watching you.)
    }
  }
}

Don't need the 'attacked' attribute. You did just what I was doing! Just faster.
It's hard to win the race when you're laying on the bed watching the tube... been scripting all day, starting to get a little worn out.
Thanks KV.


K.V.

I'm watching National Geographic: Wonders of the Universe Collection.

They are currently on Mars.
...well, the rovers are on Mars.


Just waiting for someone to post something while trying to keep from working on my own game up in here. (Know what I'm sprayin'?)


Never tried this before, but

  <command name="Stop this message">
    <pattern>Stop this message</pattern>
    <script>
          DisableTurnScript (level_notice)
	  msg("This notice will no longer display until more points are distributed.") 
	  game.notarealturn = true
    </script>
  </command>

I have at turnscript notice that pops up every turn, telling the player when they have attribute points to spend. This is a command shown at the bottom so the player can stop the message until they are ready(the notice is a bit annoying). I want it to not count as a turn, because they may be in battle at the time. However, the attacker still attacks when it is selected.

When using not a real turn should a line be used at some point to turn it back to false?


K.V.

game.notarealturn usually only effects the turn script that adds a turn when game.notarealturn is not set to true somewhere in a script.

You should have a turn script similar to this one:

if (not game.notarealturn) {
  game.turns = game.turns + 1
}
game.notarealturn = false

K.V.

You could check for that in the attack turn script (maybe):

<turnscript name="monsters_turnscript">
  <enabled />
    <script>
    if (not game.notarealturn){
      foreach (o, FilterByType(AllObjects(), "monster")) {
        if (o.parent = game.pov.parent) {
          if (o.attackonsight) {
              DoAttack (o, game.pov)
          }
          else if (o.fleeonsight) {
            o.exit = PickOneUnlockedExit (o.parent)
            msg (CapFirst(GetDisplayName(o)) + " runs away to the {exit:"+o.exit.name+"}!")
            MoveObject (o, o.exit.to)
          }
        }
      }
    }
    </script>
</turnscript>

EDITED


Added the notarealturn to the doattack script but the monster sill attacks.
I'm just home for lunch. I'll deal with this tomorrow!

      if (this.noncorporeal and GetElement(game.pov.equipped) = null) {
        if (game.pov.equipped.nonweapon) {
          msg("You attack the " + GetDisplayAlias(this) + ", and pass straight through it!")
        }
        else {
          msg("You {random:swing:stab with:thrust with} your " + GetDisplayAlias(game.pov.equipped) + " and it goes straight through the " + GetDisplayAlias(this) + "!")
        }
      }
      else if (attackroll > 10) {
        damage = GetDamage (game.pov.equipped, game.pov.strength / 2 + this.temp_damage + game.pov.damagebonus, this)
        this.hitpoints = this.hitpoints - damage
        if (this.hitpoints > 0) {
          if (game.pov.equipped.nonweapon) {
            msg ("You attack and hit, doing " + damage + " points of damage (" + this.hitpoints + " hits left). " + this.hurtbyweapon)
          }
          else {
            msg (this.temp_desc + " " + GetDisplayAlias(game.pov.equipped) + " and hit, doing " + damage + " points of damage <br></br>(Foe has " + this.hitpoints + " hits left). " + this.hurtbyweapon)
          }
          if (HasScript(this, "onweaponhit")) do (this, "onweaponhit")
          if (HasObject(game.pov.equipped, "venom")) {
            if (this.poisonimmunity) {
              if (HasString(this, "poisonimmunitymsg")) {
                msg(this.poisonimmunitymsg)
              }
              else {
                msg("The " + GetDisplayAlias(this) + " is immune to your blade venom.")
              }
            }
            else {
              game.pov.target = this
              do(game.pov.equipped.venom, "effect")
            }
            game.pov.equipped.venom = null
          }
        }
        else {
          if (game.pov.equipped.nonweapon) {
            msg ("You attack and hit, doing " + damage + " points of damage. " + this.death)
          }
          else {
            msg (this.temp_desc + " " + GetDisplayAlias(game.pov.equipped) + " and hit, doing " + damage + " points of damage. " + this.death)
          }
          do (this, "makedead")
        }
      }
      else {
        if (game.pov.equipped.nonweapon) {
          msg ("You attack and miss.")
        }
        else {
          msg ("You {random:swing:stab with:thrust with} your " + GetDisplayAlias(game.pov.equipped) + " and miss.")
        }
      }
      if (HasObject(game.pov, "secondary_attack")) {
        do(this, "secondaryattack")
      }
    }
  }	
]]></doattack>

K.V.

It doesn't display the details when I click on "Details". (It does that when I post sometimes, too. I usually just need to add an extra line-break after <details>.)


Even with your explanation, I really have no idea where to put the notarealturn. I would think in the attack script it would have worked. I have it there and in doattack. But I still get whacked.


Here's the link to game. If that helps.
Link removed for privacy....


K.V.

where to put the notarealturn

If I didn't want to call DoAttack() when game.notarealturn = True, I would put it in the turn script that called DoAttack() (assuming that's how DoAttack() is being called).

if (not game.notarealturn){
  DoAttack(f,your,parameters)
}

K.V.

How do I get to a place where someone attacks me?

(Feel free to message me, if you'd rather not broadcast the information.)


K.V.

I figured it out.

I added this turn script:

  <turnscript name="TurnCountTurnScriptKV">
    <enabled />
    <script>
      if (not HasAttribute(game,"turns")) {
        game.turns = 0
      }
      if (not game.notarealturn) {
        game.turns = game.turns + 1
      }
      game.notarealturn = false
    </script>
  </turnscript>

And I modified this turn script:

  <turnscript name="attacktheplayerturnscript">
    <enabled />
    <script><![CDATA[
      // In an ideal world, this would only fire if the player has actually done something.
      // As it is, a mis-typed command will give monsters the opportunity to strike
      // so we have thisL
      //
      // KV was here!  I added the next if statement.
      if (not game.notarealturn) {
        if (game.command_successful) {
          game.pov.turncount = game.pov.turncount + 1
          // Anything added to this list will later get removed from the attackers list
          game.forgetme = NewObjectList ()
          // Any monsters here that need adding to the list of attacks because they attack on sight?
          foreach (obj, GetDirectChildren (game.pov.parent)) {
            if (DoesInherit(obj, "monster") and not ListContains(game.attackers, obj) and not ListContains(game.friends, obj)) {
              do (obj, "initattack")
            }
          }
          // Go through each monster
          monsters = ListCombine(game.attackers, game.friends)
          list remove (monsters, player)
          foreach (attacker, monsters) {
            if (GetBoolean(attacker, "stunned")) {
              if (attacker.parent = game.pov.parent) {
                msg (attacker.alias + " is stunned for a moment, and does not attack.")
              }
              attacker.stunned = false
            }
            else if (attacker.parent = game.pov.parent) {
              do (attacker, "selecttarget")
              if (HasObject(attacker, "target")) {
                do (attacker, "attackplayer")
              }
              else {
                msg (CapFirst(GetDisplayName(attacker)) + " has no target to attack.")
              }
            }
            else {
              do (attacker, "searchforplayer")
            }
          }
          // These are no longer attackers or friends=
          foreach (mon, game.forgetme) {
            list remove (game.attackers, mon)
            list remove (game.friends, mon)
          }
          // Check for spell/potion expiring
          if (not HasInt(game.pov, "magiccountdown")) {
            game.pov.magiccountdown = 0
          }
          if (game.pov.magiccountdown > 0) {
            game.pov.magiccountdown = game.pov.magiccountdown - 1
            if (game.pov.magiccountdown < 1) {
              do (game.pov.currentspell, "endmagiceffect")
            }
          }
          // Check sneaking
          if (not HasInt(game.pov, "sneaklevel")) {
            game.pov.sneaklevel = 0
          }
          game.pov.sneaklevel = game.pov.sneaklevel - 1
          if (0 > game.pov.sneaklevel) {
            game.pov.sneaklevel = 0
          }
          // Some attacks give a bonus to OB next round
          game.pov.ob_bonus = game.pov.next_round_ob_bonus
          game.pov.next_round_ob_bonus = 0
          game.pov.db_bonus = 0
          game.pov.currectattack = null
        }
        else {
          game.command_successful = true
        }
      }
    ]]></script>
  </turnscript>

Now game.notarealturn gets set to false after every turn, whether it's a real command or not (which is how it should be), and the monsters don't attack when game.notarealturn is true.


I just had to add this to the command that stopped the "level notice" from popping up.

game.notarealturn = true 

That was the issue. A notice will print every turn if the player has attribute points to spend. I'd hate to have the player forget they had them and miss out. But the notice is annoying. This gives them the option to shut it off especially if they are in battle. Everything works now KV.

I never would have figured this out, but now that I see it in action I understand the who, what, where of it.
Thanks again.
BTW, I edited the uploaded game. Now I just have a couple months of adding the old game contents a piece at a time to finish it. It has only been 2 years already...


K.V.

Aha!

You were like Sherlock Holmes, and I was like Jiminy Cricket!


Or Dumb and Dumber


So I was thinking... I have been on the forum for years now. I should start a thread called " The Documentary of a Text Adventure" and it would show the steps involved, since I'm starting over. It would show the failures, successes, processes, and pitfalls involved in making a game. As well as the dedication it takes to create a truly crappy...wait, that's epic game.

And....I'm over it.


Ha.

I think this whole big forum is like one big tutorial. That's what it's there for, anyway.

"Oh hey, I have an idea, but I don't know how to do this?"

"I don't understand any of this..."

"Yay! I found useful code!"

"That didn't work, that didn't work, that didn't work..."

One day later.

"That didn't work, that didn't work, that didn't work..."

Three days later.

"Yes! It works now! Wait, now this is broken..."

Repeat the process for weeks, months, or years. Then publish the game, and then realize you have more bugs, and then spend one or two months getting those bugs out.
At least that's my experience.


jmnevil54,
Exactly. Then there updates and newly learned code that you just have to have in your game causing you to start over or redo.


gives you a lot of appreciation/respect for game makers (even if they're massive teams of big gaming companies), especially in the early days of gaming... where there wasn't massive teams, but only a few people, or even just one, making a game.


That's the problem with updating, unfortunately... I'm still using like quest 5.5.X, I've not even tried/downloaded/installed Pixie's quest versions... I'm just trying to learn how to code in things myself, even if Pixie has already coded such things in, I learn a lot by trying to do it myself, and I understand what I worked on and created, whereas it's not easy for me to learn other people's code and features, including the default/built-in quest's coding/features, laughs.


the worst is having a lot of code, and going back and changing your naming/labeling and/or coding structure system/convention, lol... I probably should learn to code in code, to do this for me (compiling/parsing/etc coding), laughs.


90% of coding, isn't coding... but trouble-shooting code and/or re-designing/re-coding (re-factoring/stream-lining) your code, lol.


When using the hitpoint table indicator from

Custom Panes

I have had an issue with it from day one. Everything thing works but the Hitpoints are not shown in the top until an attack occurs. The label is there but the integers are just ---. I'm sure this has to do with the ChangedHitpoints attribute. I would like the integers to show from the get go.

I have made some changes to the script concerning colors.

s = "<table width=\"100%\"><tr>"
s = s + "   <td style=\"text-align:right;\" width=\"50%\">Hit points:</td>"
s = s + "   <td style=\"text-align:left;\" width=\"50%\"><span id=\"hits-span\">---</span></td>"
s = s + " </tr>"
s = s + " <tr>"
s = s + "   <td colspan=\"2\" style=\"border: thin solid;background:linen;text-align:left;\">"
s = s + "   <span id=\"hits-indicator\" style=\"background-color:green;padding-right:200px;\"></span>"
s = s + "   </td>"
s = s + " </tr>"
s = s + "</table>"
JS.setCustomStatus (s)
if (HasScript(player, "changedhitpoints")) {
  do (player, "changedhitpoints")
}

I set the InitUserInterface in start as well as the hitpoints and max Hitpoints, which combatLib changes anyway.


K.V.

I am making an RPG so I can be of more help to those of you who are doing the same.

This is what I've got on my player object.

      <object name="player">
        <inherit name="editor_object" />
        <inherit name="editor_player" />
        <feature_startscript />
        <attr name="_initialise_" type="script"><![CDATA[
          msg("Running player initialise script")
          player.alias = "you"
          //player.hitpoints = 35
          player.damage = 3
          player.attack = 0
          player.defence = 0
          player.armour = 0
          player.changedhitpoints => {
            if (player.hitpoints > 0) {
              msg ("Hit points now: " + player.hitpoints)
            }
            else {
              msg ("You have died!")
              finish
            }
          JS.eval ("$('#hits-span').html('" + game.pov.hitpoints + "/" + game.pov.maxhitpoints + "');")
          JS.eval ("$('#hits-indicator').css('padding-right', '" + (200 * game.pov.hitpoints / game.pov.maxhitpoints) + "px');")
          }
          player.maxhitpoints = 100
          player.hitpoints = 100
        ]]></attr>
      </object>

NOTE: You can set maxhitpoints and hitpoints to whatever you please and the thingy will still work.


My start script:

    <start type="script"><![CDATA[
      msg("Running start script")
      // List of attackers
      player.attackers = NewObjectList()
      player.ammo = 35
      // Status attributes
      WeaponUpdate
      player.statusattributes = NewStringDictionary()
      dictionary add (player.statusattributes, "hitpoints", "Hit points: !")
      dictionary add (player.statusattributes, "ammo", "Spare ammo: !")
      dictionary add (player.statusattributes, "equippedname", "Weapon: !")
      dictionary add (player.statusattributes, "ammonote", "Ammo: !")
      SetTurnTimeout(1){
        SetDate
      }
      s = "<table width=\"100%\"><tr>"
      s = s + "   <td style=\"text-align:right;\" width=\"50%\">Hit points:</td>"
      s = s + "   <td style=\"text-align:left;\" width=\"50%\"><span id=\"hits-span\">---</span></td>"
      s = s + " </tr>"
      s = s + " <tr>"
      s = s + "   <td colspan=\"2\" style=\"border: thin solid;background:linen;text-align:left;\">"
      s = s + "   <span id=\"hits-indicator\" style=\"background-color:green;padding-right:200px;\"></span>"
      s = s + "   </td>"
      s = s + " </tr>"
      s = s + "</table>"
      JS.setCustomStatus (s)
      if (HasScript(player, "changedhitpoints")) {
        do (player, "changedhitpoints")
      }
    ]]></start>

While we're here, want to see the order in which the start and initialisation script run?

Running user interface initialisation script
Running start script
Running player initialise script
Running junk pile initialise script
Running Cricket Bat initialise script
Running vomitattack initialise script
Running vomitreadying initialise script
Running kickattack initialise script
Running Spade initialise script


That is the order the objects are entered in full code view, by the way.


K.V.

image

image


Somehow during changing things I was missing this in player Initializing script.

JS.eval ("$('#hits-span').html('" + game.pov.hitpoints + "/" + game.pov.maxhitpoints + "');")
JS.eval ("$('#hits-indicator').css('padding-right', '" + (200 * game.pov.hitpoints / game.pov.maxhitpoints) + "px');") 

K.V.

Tisk, tisk!


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums