Author Topic: Scripting Enemy/Ally/Enemy/Enemy conditions  (Read 1473 times)

Offline cmorgan

  • Planewalker
  • *****
  • Posts: 1424
  • Gender: Male
  • Searcher of Bugs
Scripting Enemy/Ally/Enemy/Enemy conditions
« on: May 21, 2006, 09:18:36 AM »
Before getting too far into exploring a concept to add to Tutu, could the combined wisdom here indicate if this concept is possible within the confines of BG2/Tutu scripting?

Player1's Party
encounters
Faction A
who is enemy to
Faction B
who is enemy to
Faction C
over a quest object (or simply to determine good, neutral, evil, or solo pathway for continuing the quest).

If Player1's party allies with A, then B and C become hostile to eachother as well as P1 and A
If Player1's party allies with B, then A and C become hostile to eachother as well as P1 and B
If Player1's party allies with C, then A and B become hostile to eachother as well as P1 and C
If Player1's party stays neutral, then A, B, and C become hostile to eachother until only one faction is left. Then easy scripting; P1 vs Remaining Faction or Ally with remaining faction.
If Player1's party says "bring it on, I 'm getting this for myself", then everyone attacks everyone else in mass mayhem mode.

Possible, and if so, starting examples of Enemy/Ally forced .cre vs .cre, instead of/with Player1, etc?

Offline Duality

  • Planewalker
  • *****
  • Posts: 147
Re: Scripting Enemy/Ally/Enemy/Enemy conditions
« Reply #1 on: May 23, 2006, 07:10:58 PM »
I'm not sure if there is a "good" way to do this, but I have been recently trying to do something similiar and come up with a workable, if somewhat messy, solution. Ok, make that very messy.

The ally piece is easy, just set the NPC's the player allies with to [GOODCUTOFF], that way, anyone who is marked as [ENEMY] will attack them.

The enemy attacks enemy piece is a where it gets messy.
The only way I could figure out how to do it was to have the NPC's scripts force them to attack each NPC on the other side individually. This quickly gets out of control if each side has 10+ different types of fighters on the field. And mages are even worse. I'm not sure how you would even make a mage script that wasn't 500 lines long.

Anyway, I was trying to have a scenario where Baatezu would fight Tanar'ri and vice versa, all the while attacking the player and some temple guards who were allied with the player. This meant that the Baatezu's scripts looked something like this:

IF
   See("Tana01")
THEN
   RESPONSE #100
      Attack("Tana01")
      Continue()
END

IF
   See("Tana02")
THEN
   RESPONSE #100
      Attack("Tana02")
      Continue()
END

and so on for each type of Tanar'ri. (I only had 5 types so it wasn't so bad) The Tanar'ri's scripts looked exactly the same but with the Baatezu DV's instead.
This way, whoever they see, they will attack.

I also had the requisite:
See(NearestEnemyOf(myself))
Attack(NearestEnemyOf(myself)) at the end.

The only problem is that sometimes a NPC will get fixated on one target and refuse to retarget even if they are being beaten on by someone else. That's why I added the continues, but it didn't seem to help.

With your scenario, it might be wise to make multiple scripts for each side, one for if the player allies with A, one for B, one for C and one for mayhem mode. That way each script only has to target one side (except for mayhem of course) at a time. This would limit the number of unnecessary checks that the engine had to make.

If someone has a better way of doing this I would love to hear it since this has very limited applications in terms of the number of actors that can be used before the scripts become to long to run efficiently. And it requires a lot of cut/paste.

Hope that helps. If you come up with anything better feel free to share  ;D
« Last Edit: May 23, 2006, 07:15:09 PM by Duality »
"I'll try being nicer if you try being smarter."

"There is a certain freedom in being totally screwed. It means that nothing you do is going to make it any worse."

"Eagles may soar, but weasels don't get sucked into jet engines."

Offline cmorgan

  • Planewalker
  • *****
  • Posts: 1424
  • Gender: Male
  • Searcher of Bugs
Re: Scripting Enemy/Ally/Enemy/Enemy conditions
« Reply #2 on: May 23, 2006, 09:32:17 PM »
Interesting and creative workaround :D! I thought of using 3 potential cutscenes with predetermined outcomes, and one pvp Mass Mayhem Madness, but did not make the conceptual leap from cutscene to actual in-game BCS - if we can script the behavior in a cutscene, why not directly in-game? Just script the cre vs cre matchups, and then CHARNAME and party clean up the leftovers (with allies if present/chosen).

Since each scenario is called for by a dialog response, I can see having the dialog responses either reset the scripts (XSCRIPT1 or 2 or 3 or 4) on each cre, or simply have different "reinforcements" cres created if option 1 2 3 or 4 are chosen. In that case, scripts could be pretty small (not much more than you have posted).

From a player complexity and survival point of view (since I am talking Tutu here, with levels aimed at a party of 4 to 6 3rd or 4th level characters) it might be ok to have the "fixation" problem - and I am looking at relatively small numbers of people in each faction. This means that some version of this idea is possible to implement, and it might be ok to continue exploring the coding possibilities of the quest. Thanks for sharing the idea - if the quest gets off the ground, you will definitely get the credit!

« Last Edit: May 23, 2006, 09:37:52 PM by cmorgan »

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Scripting Enemy/Ally/Enemy/Enemy conditions
« Reply #3 on: May 24, 2006, 01:34:26 AM »
I don't want to read the whole thread right now, but you want See("blah") !Dead("blah"). See() sees dead people, and they're not worth attacking. :)

Offline Duality

  • Planewalker
  • *****
  • Posts: 147
Re: Scripting Enemy/Ally/Enemy/Enemy conditions
« Reply #4 on: May 24, 2006, 03:55:42 PM »
Quote from: cmorgan
Since each scenario is called for by a dialog response, I can see having the dialog responses either reset the scripts (XSCRIPT1 or 2 or 3 or 4) on each cre, or simply have different "reinforcements" cres created if option 1 2 3 or 4 are chosen. In that case, scripts could be pretty small (not much more than you have posted).


Thinking soley about how many files you are putting into the override folder, changing scripts might be for the best. You're going to need different scripts no matter which way you go, so the extra .cre's seem redundant.

Quote
From a player complexity and survival point of view (since I am talking Tutu here, with levels aimed at a party of 4 to 6 3rd or 4th level characters) it might be ok to have the "fixation" problem - and I am looking at relatively small numbers of people in each faction. This means that some version of this idea is possible to implement, and it might be ok to continue exploring the coding possibilities of the quest. Thanks for sharing the idea - if the quest gets off the ground, you will definitely get the credit!


Hm... good point. I saw the tutu reference, but it didn't register  :)
I hope it works out! Personally, I like battles that are more complex then just side A and side B beat each other senseless.

Quote from: devSin
I don't want to read the whole thread right now, but you want See("blah") !Dead("blah"). See() sees dead people, and they're not worth attacking. :)


It's not THAT long.  :P
If you know another way to do this devSin, or even a way to streamline things, I would appreciate your input. This method becomes far less useful when a larger number of creatures are introduced. (Plus it feels like a total hack job to me, and I find that annoying)

Wouldn't the lack of the !Dead() mean that the NPCs would spend quite a bit of time standing around, thinking that they are attacking someone, but the someone happens to be dead, so they do nothing?

The reason I ask is because I was testing this, and the NPC's didn't exibit any odd behavior. I tried it with 5 creatures on each side (there are three sides) and 15 creatures on each side (THAT was messy), and each time things seemed to work fine, with the exception of the fixation problem. The NPCs would retarget as soon as their current target was dead. And the fixation issue only seemed to occur sporadically. Plus, the fixation problem solved itself as soon as the target of a NPCs fixation died.

Actually, the only reason I didn't put !Dead in initially is because I'm lazy and I didn't feel like typing an extra line, and when I copied and pasted from my script to post here, I.... errr.. forgot about it totally. Plus, I wasn't sure this would actually work. But then it didn't seem to matter, so I left it out.
« Last Edit: May 24, 2006, 03:58:29 PM by Duality »
"I'll try being nicer if you try being smarter."

"There is a certain freedom in being totally screwed. It means that nothing you do is going to make it any worse."

"Eagles may soar, but weasels don't get sucked into jet engines."

Offline devSin

  • Planewalker
  • *****
  • Posts: 1632
  • Gender: Male
Re: Scripting Enemy/Ally/Enemy/Enemy conditions
« Reply #5 on: May 24, 2006, 08:00:40 PM »
The game probably doesn't let Attack() run for dead targets, so it just continues on to the next block. Bad form, but not the end of the world.

Scripting some sort of faction system isn't my cup of tea. I would give everyone a unique object type (maybe a special race or specific value), and roll it all into one big "SomeConditions() + See([customObjId]) + OtherConditions()" check. It still sucks, but you only need one block that says "I see opposite faction, attack" instead of creature by creature.
« Last Edit: May 24, 2006, 08:05:11 PM by devSin »

Offline cmorgan

  • Planewalker
  • *****
  • Posts: 1424
  • Gender: Male
  • Searcher of Bugs
Re: Scripting Enemy/Ally/Enemy/Enemy conditions
« Reply #6 on: May 24, 2006, 09:36:11 PM »
devSin, it sounds like the idea you are suggesting here could be implemented this way:

Script switch set in-dialog, with conditions
Code: [Select]
++ ~I choose A~ DO SetGlobal("AlliedGood","GLOBAL",1) EXIT
++ ~I choose B~ DO SetGlobal("AlliedBad","GLOBAL",1) EXIT
++ ~I choose C~ DO SetGlobal("AlliedNeutral","GLOBAL",1) EXIT
++ ~Bring it on.~ EXIT
3 separate object IDS entries, added to CLASS.IDS or RACE.IDS and set via tp2 into COPY_EXISTING for .cres:
 [GOODFAC] [BADFAC] [NEUTFAC]

One script, assigned to all spawned cres:

Code: [Select]
IF
    Global("AlliedGood","GLOBAL",0)
    OR (2)
    !See([BADFAC])
    !See([NEUTFAC])
THEN
    RESPONSE #100
    Attack(LastSeenBy(Myself))
    Continue()
END

IF
    Global("AlliedBad","GLOBAL",0)
    OR (2)
    !See([GOODFAC])
    !See([NEUTFAC])
THEN
    RESPONSE #100
    Attack(LastSeenBy(Myself))
    Continue()
END   

IF
    Global("AlliedNeutral","GLOBAL",0)
    OR (2)
    !See([GOODFAC])
    !See([BADFAC])
THEN
    RESPONSE #100
    Attack(LastSeenBy(Myself))
    Continue()
END         

If I read this right, the scripts will cycle through, targeting LastSeenBy until it hits the global=1 condition (or in the mass mahem scenario it doesn't) where it skips the block and continues cycling until all other factions are no longer present.

Wait -- we also need to set the [faction] groups hostile... damn. more research for me, I'm afraid. Am I at least close?

 

With Quick-Reply you can write a post when viewing a topic without loading a new page. You can still use bulletin board code and smileys as you would in a normal post.

Warning: this topic has not been posted in for at least 120 days.
Unless you're sure you want to reply, please consider starting a new topic.

Name: Email:
Verification:
Type the letters shown in the picture
Listen to the letters / Request another image
Type the letters shown in the picture:
What color is grass?:
What is the seventh word in this sentence?:
What is five minus two (use the full word)?: