Jump to content


Photo

Gonna DIE if I don't get help for this


  • Please log in to reply
7 replies to this topic

#1 Bardess

Bardess

    the Eternal Noob

  • Modder
  • 483 posts

Posted 08 December 2008 - 12:46 PM

In order to finally publish that little mod that's been giving me unproportionally lots of headache, I need advice on how to script/do the following.
This is for BG1 TuTu.

In one talk, PC chooses his/her side, which can result in four cases.

#1
Four NPCs become hostile to PC and are supposed to actually attack and not just stand in place. Do I tell them to do this through the dialogue file, or some script, cutscene, or how? I'm really going mad. They also need to apply some spells to themselves, so the list of things they need to do is kind of long. What attack/hostility commands should I use?

#2
No one becomes hostile to PC, but two groups of NPCs start fighting each other. How to do?? :(

#3
One group of NPCs becomes hostile (and does not necessarily attack), and the other group joins the PC in fighting them.

#4
Some eight people become hostile and attack (though I suppose I'll get to know about this procedure from the first case).


Help, please!

Edited by Bardess, 08 December 2008 - 12:48 PM.

"Farewell, Charname, and may Irenicus get you!"

Mazzy to Edwin:
"When science finally locates the center of the planes, I'm sure you'll be taken aback to find that you're not it."

- Author of lil one-day Moddie fox. -


#2 Icendoan

Icendoan

    "An Infinite Deal of Nothing"

  • Member
  • 1723 posts

Posted 08 December 2008 - 01:08 PM

This is only a very basic solution. If you plan for more advanced AI, I will explain how. :)

#1

Well, dialogue is easier, if they are talking, or related to the person talking. Use ActionOverride("charDV",Attack(PlayerX)) for each of them.

#2

ActionOverride("charDV",Attack("opponentDV")) ActionOverride*"charDV",Enemy()) or just Attack("opponentDV") Enemy() works great

#3

IF
See([ENEMY])
//Global("OptionThreeAttack","GLOBAL",1) //Advanced AI method
THEN
RESPONSE #100
Attack(NearestEnemyOf(Player1))
Enemy()
END

ActionOverride("npc1",Attack([PC])) ActionOverride("npc1",Enemy()) //If the dialogue is by the attacker. Otherwise, switch the roles.

#4

The PC?

ActionOverride("charDV",Attack(Player1))

For dialogue, it would be something like this
IF ~~ THEN BEGIN fight-choice
SAY ~blah blah blah~
+ ~triggers~ + ~option one~ DO ~ActionOverride("npc1",Attack([PC])) ActionOverride("npc2",Attack([PC])) ActionOverride("npc3",Attack([PC])) Attack([PC]) ActionOverride("npc1",Enemy())...~ EXIT //simple AI
+ ~triggers~ + ~option one~ DO ~SetGlobal("OptionOneHostile","GLOBAL",1)~ EXIT //Uses a global so that a script with mage attacks and so on can be used
+ ~triggers~ + ~option two~ DO ~ActionOverride("group11",Attack("group21")).... ActionOverride("group11",Enemy())~ EXIT //ActionOverride()s for all, each with different targets and so on, or a cleaner, nicer method
+ ~triggers~ + ~option two~ DO ~SetGlobal("OptionTwoGroups","GLOBAL",1)~ EXIT //Individual scripts will trigger, allows for a nicer D file and advanced AI
+ ~triggers~ + ~option three~ DO ~ActionOverride("npc1",Attack(NearestEnemyOf(Player1)) ActionOverride("npc2",Attack([PC])) ActionOverride("npc1",Enemy()) ActionOverride("npc2",Enemy())~ EXIT //Basic AI, standard attacks
+ ~triggers~ + ~option three~ DO ~SetGlobal("OptionThreeAttack","GLOBAL",1)~ EXIT //Advanced method
+ ~triggers~ + ~option four~ DO ~ActionOverride("npc1",Attack([PC])) ActionOverride("npc1",Enemy())/*You know the drill...*/~ EXIT //Basic attacks
+ ~triggers~ + ~option four~ DO ~//YOU KNOW THAT I WILL SET A GLOBAL HERE, DON'T YOU!
END

Time to update my location count!

EDIT: Forgot Enemy()

Icen

Edited by Icendoan, 08 December 2008 - 01:54 PM.

Proud member of the 'I HATE Elminster!' Club!

Mods in development: Keeping Yoshimo

#3 Jarno Mikkola

Jarno Mikkola

    The Imp in his pink raincoat.

  • Member
  • 10911 posts

Posted 08 December 2008 - 01:36 PM

:whistling:

...

Well, the easier way is to set the creature alliances... and this is all done in scripting after the dialog options according to the outcome.
With this:
ActionOverride("DV",ChangeEnemyAlly(Myself,x*)) ... where the x* is the name, so it's GOODBUTBLUE, ENEMY etc.

This is done to each character according to the outcome by one master script, usually by the speakers script, so the master script looks something like this:
IF 
   Global("Attackoutcome","GLOBAL",1)
THEN
   ActionOverride("DV1",ChangeEnemyAlly(Myself,ENEMY))
   ActionOverride("DV2",ChangeEnemyAlly(Myself,ENEMY))
   ActionOverride("DV3",ChangeEnemyAlly(Myself,ENEMY))
   ActionOverride("DV4",ChangeEnemyAlly(Myself,ENEMY))
   SetGlobal("Attackoutcome","GLOBAL",5)
END

IF 
   Global("Attackoutcome","GLOBAL",2)
THEN
...
And the dialogs outcome sets the "Attackoutcome"s Global count to what it needs to be to trigger the attacks. And the creatures general script does the attacking and fighting when it's set on WTASIGHT.BCS(fighter script).

Edited by Jarno Mikkola, 09 December 2008 - 03:39 AM.

Deactivated account. The user today is known as The Imp.


#4 GeN1e

GeN1e

    A very GAR character

  • Modder
  • 1604 posts

Posted 08 December 2008 - 04:09 PM

So, it's about time for the GeN1us of cutscenes to make his move once again :)

You'll need to make two different creaures, one is to be a member of the first group of NPCs, another - of the second. The only difference between them is their death variables.

IF ~Trigger()~ THEN BEGIN PC_decides_what_to_do
  SAY ~Choose your side <CHARNAME>~
  IF ~~ THEN REPLY ~I choose the option 1, to fight 4 evil guys.~ DO ~SetGlobal("select_option","GLOBAL",1)~ EXIT
  IF ~~ THEN REPLY ~I choose the option 2, to watch goods and evils fighting.~ DO ~SetGlobal("select_option","GLOBAL",2)~ EXIT
  IF ~~ THEN REPLY ~I choose the option 3, to help goods to defeat evils.~ DO ~SetGlobal("select_option","GLOBAL",3)~ EXIT
  IF ~~ THEN REPLY ~I choose the option 4, to fight all of you.~ DO ~SetGlobal("select_option","GLOBAL",4)~ EXIT
END

//This should be assigned to evil NPCs

IF // turning red, to simplify the matter for PCs
OR(3)
Global("select_option","GLOBAL",1) // only we're against PC, goods just stand and watch
Global("select_option","GLOBAL",3) // against PC and goods
Global("select_option","GLOBAL",4) // every one against PC
!Allegiance(Myself,ENEMY)
THEN
RESPONSE #100
Enemy()
END

IF
OR(2)
Global("select_option","GLOBAL",1) // against PC
Global("select_option","GLOBAL",4) // against PC, and we're accompanied by goods
See([PC])
THEN
RESPONSE #100
AttackReevaluate(LastSeenBy(Myself),6)
END

IF
Global("select_option","GLOBAL",2)
See("GoodGuy") // GoodGuy - death variable of every member of the 1st group
THEN
RESPONSE #100
AttackReevaluate(LastSeenBy(Myself),6)
END

IF
Global("select_option","GLOBAL",3)
OR(2)
See([PC])
See("GoodGuy")
THEN
RESPONSE #100
AttackReevaluate(LastSeenBy(Myself),6)
END


//This should be assigned to good NPCs

IF
OR(2)
Global("select_option","GLOBAL",2) // fighting evils according to 2nd scenario
Global("select_option","GLOBAL",3) // fighting evils according to 3rd scenario, PC is supposed to assist here
See("EvilGuy")  // EvilGuy - death variable of every member of the 2nd group
THEN
RESPONSE #100
AttackReevaluate(LastSeenBy(Myself),6)
END

IF // turning red, to simplify the matter for PCs
Global("select_option","GLOBAL",4)
!Allegiance(Myself,ENEMY)
THEN
RESPONSE #100
Enemy()
END

IF
Global("select_option","GLOBAL",4)
See([PC])
THEN
RESPONSE #100
AttackReevaluate(LastSeenBy(Myself),6)
END

PS The reason for AttackReevaluate(...,6) is that the attacker won't lock onto a single enemy (it's rather annoying to have a fighter chasing your mage not matter what, not to mention it looking stupid). You may want to alter the names of variables, death or not, otherwise just copypaste scripts and hopefully they'll work as expected.

Edited by GeN1e, 08 December 2008 - 04:23 PM.

Retired from modding.


#5 Icendoan

Icendoan

    "An Infinite Deal of Nothing"

  • Member
  • 1723 posts

Posted 08 December 2008 - 04:42 PM

All of these suggestions are valid. Gen1e's is pretty good, and a little cleaner than mine. Jarno is covered in both mine and Gen1e's.

Icen
Proud member of the 'I HATE Elminster!' Club!

Mods in development: Keeping Yoshimo

#6 SConrad

SConrad

    I swear to drunk I'm not God

  • Administrator
  • 11149 posts

Posted 08 December 2008 - 06:20 PM

IF
See([ENEMY])
//Global("OptionThreeAttack","GLOBAL",1) //Advanced AI method
THEN
RESPONSE #100
Attack(NearestEnemyOf(Player1))
Enemy()
END

Won't work. If the creature this script is assigned to isn't already an enemy of the party (which is set in the block), the block triggers won't evaluate to true.

In general, I recommend setting Enemy() before Attack() purely because of semantics. Under certain circumstances, the creature might attack before the circle is red, which could look a little bit funky.

All in all, GeN1e's suggestion probably is the best one offered so far.

Posted Image Khadion NPC mod - Team leader, head designer
Posted Image Hubelpot NPC mod - Team leader, coder
Posted Image NPC Damage - Coder
Posted Image PC Soundsets - Coder, voice actor
Posted Image Brythe NPC mod - Designer
Posted Image DragonLance TC - Glory of Istar - Designer
Posted Image The NPC Interaction Expansion Project - Writer for Cernd, Sarevok
Posted Image The Jerry Zinger Show - Producer

Iron Modder 5 - Winner


#7 cmorgan

cmorgan
  • Modder
  • 2301 posts

Posted 08 December 2008 - 07:10 PM

Of course, they can't be Party-Joinables that have joined the party - that makes things more complicated. Take a look at the Edwin/Dynaheir/Minsc scripting, after applying WizWom's fix for it (just decompile a bg1npc EasyTutu install)

This actually was an old abandoned Imoen idea for BG1NPC, too - it got shelved because of the difficulties of scripting and cutscene inetractions. We got as far as messing with creating specialized Class (swap INNOCENT for a new value X#IMQU1, X#IMQU2) and creating custom Shout() categories - and trying to create conditions in which groups of NPCs could be manipulated. We ran into the "everone ends up against the party or for the party" thing raiding ideas from (I think) Zyraen's works. Eventually we shelved it because it was really hideous to test and get consistently working.

I admire you wanting to do this, but is there a way you can play out most of it by cutscene, and alter the storyline to have easier outcomes? If you really want to tackle this, though, take a look at the dialog/script interaction for the Fallen Paladin quest in BG2. It should give you some good ideas of how to try the ideas these folks have provided for you :)

#8 Kulyok

Kulyok
  • Modder
  • 2450 posts

Posted 09 December 2008 - 03:05 AM

I wanted to do something similar in Dungeon Crawl(see the fight in the Docs). In the end, I decided against it. Simple is better.