ID:1510471
 
Dial
var/npct = "" //What the NPC will say
var/responses = list() // The available player responses

Resp
var/respt // What the response will say
var/Dial/next // Which Dialogue text the response will lead to.

mob
var
mob/talktarget // Who am I talking to?
Dial/activeDial // Which Dialogue message am I reading? (To prevent cheating with the "Topic")

proc
ShowDial() // This makes the Dialogue window pop up
winshow(src,"dial",1)

GetDial(mob/M,Dial/D) // Change what's showing in your dialogue window.
src.talktarget = M
src.activeDial = D // Remember which Dial is active so we can verify that a selected response is valid

if(D)
src << browse("<body bgcolor=black><font color=white><h3>[M.name]</h3><p>[D.npct]</p></font></body>", "window=dial")

var/i=1 //For our grid. This number changes per Resp.
for(var/Resp/R in D.responses) //We have Dial, now what datums are in the responses list?
src<<output("<a href='?src=\ref[src];action=respond;response=\ref[R]'>[R.respt]</a>","playerchoice:1,[i++]")

winset(src, "playerchoice", {"cells="1x[i-1]"})

mob
Topic(href,href_list[])
switch(href_list["action"])
if("respond") // If the link had its action set to "respond"
var/respId = href_list["response"] // Get the /Resp object's ID from the link's "response" param
var/Resp/R = locate(respId) // Use locate() to get the object based on the ID
if(istype(R) && activeDial && (R in activeDial.responses)) // Verify that this is a valid object, and not an old/spoofed link
GetDial(src.talktarget,R.next)


This is a dialogue system that I was troubleshooting a few months ago in the Developer Help forums. I'm now making the code free to use, no credits needed.


This obviously needs a little bit more explanation. The dialogue options and responses are handled like they are in The Elder Scrolls, where each player response and all of the NPC's lines are game objects. They are called Dial and Resp. Each Dial has a list of responses that the player can use, and they are all stored as Resp datums.

You can fool around with the code to make some Dials enable quests. I couldn't include this because each game handles quests differently.


Example of this snippet in action:


Dial
Greet
npct = "Greetings, traveller! How are you?"
responses = list(/Resp/Happy, /Resp/Mad)
Happy
npct = "Well, I'm glad to hear that! I'll be on my way!"
Mad
npct = "Oh, I'm sorry to hear that! I'll leave you alone!"

Resp
Happy
respt = "I'm doing great!"
next = /Dial/Happy
Mad
respt = "To be honest, I'm not doing too well, today. :("
next = /Dial/Mad

mob
OldMan
verb/talk()
ShowDial()
GetDial(src, /Dial/Greet)
This is a really cool piece of code. The only concern I have is to do with your snippet. It groups all Dials and Resps together. That's not really very organized. As well as just not being organized it could lead to bugs where NPCs end up using other NPC's Dials/Resps because there's nothing stopping them.

Instead I'd suggest organizing it like this to maximize it's maintainability and bug proofing.

Just my thoughts on it.

Dial/Old_Man

Greet
npct = "Greetings, traveller! How are you?"
responses = list(/Resp/Old_Man/Happy, /Resp/Old_Man/Mad)
Happy
npct = "Well, I'm glad to hear that! I'll be on my way!"
Mad
npct = "Oh, I'm sorry to hear that! I'll leave you alone!"

Resp/Old_Man

Happy
respt = "I'm doing great!"
next = /Dial/Old_Man/Happy
Mad
respt = "To be honest, I'm not doing too well, today. :("
next = /Dial/Old_Man/Mad

mob
Old_Man
verb/talk()
ShowDial()
GetDial(src, /Dial/Old_Man/Greet)


{Added an underscore to the object's name because typically the default name is going to be used and a space will make it more readable. }
This looks extremely helpful i'll be sure to use it.
I likey
runtime error: bad client
proc name: ShowDial (/mob/proc/ShowDial)
usr: Guest-320239361 (/mob)
src: Old Man (/mob/Old_Man)
call stack:
Old Man (/mob/Old_Man): ShowDial()
Old Man (/mob/Old_Man): talk()
runtime error: Cannot read /Dial/Old_Man/Greet (/Dial/Old_Man/Greet).npct
proc name: GetDial (/mob/proc/GetDial)
usr: Guest-320239361 (/mob)
src: Old Man (/mob/Old_Man)
call stack:
Old Man (/mob/Old_Man): GetDial(Old Man (/mob/Old_Man), /Dial/Old_Man/Greet (/Dial/Old_Man/Greet))
Old Man (/mob/Old_Man): talk()

Runtime error doesnt work.
mob
Old_Man
verb/talk()
ShowDial()
GetDial(src, /Dial/Old_Man/Greet)


You made a mistake here. It should be:

mob
Old_Man
verb/talk()
ShowDial()
GetDial(usr, /Dial/Old_Man/Greet)
same result

runtime error: bad client
proc name: ShowDial (/mob/proc/ShowDial)
usr: Guest-320239361 (/mob)
src: Old Man (/mob/Old_Man)
call stack:
Old Man (/mob/Old_Man): ShowDial()
Old Man (/mob/Old_Man): talk()
runtime error: Cannot read /Dial/Old_Man/Greet (/Dial/Old_Man/Greet).npct
proc name: GetDial (/mob/proc/GetDial)
usr: Guest-320239361 (/mob)
src: Old Man (/mob/Old_Man)
call stack:
Old Man (/mob/Old_Man): GetDial(Guest-320239361 (/mob), /Dial/Old_Man/Greet (/Dial/Old_Man/Greet))
Old Man (/mob/Old_Man): talk()
Also, I really don't think you should be using polymorphism as a sort of database.

I'd recommend setting up dialogue trees in another manner:

dialogue
var
list/messages
New(list/msg)
messages = msg
choice
var
list/options
New(list/msg,list/opts)
options = opts
. = ..(msg)


var
list/dialogue_tree = list("someconversation"=new/dialogue(list("message1","message2","message3","message4")),"someconversation2"=new/dialogue/choice(list("message1"),list("choice1","choice2")))


mob
NPC
var
conversation = "someconversation"


You can display them however you want, but ultimately, you don't need to assign a type per option. Better to store a series of initialized general conversation objects globally, than to have a type per conversation.
I just want to use these for quests and stores pretty much.
Yeah... It's just a really bad example in general. The approach GamerMania posted is broken fundamentally, not just in that the code doesn't do what he thinks it does, but also the underlying behavior itself is poorly designed.

I don't have time tonight, but I'll see about putting together a better example using Javascript, CSS, and HTML.
When is this getting fixed?
(Developer Announcement)


I'd recommend waiting for Ter13's fix if it really is more efficient. I think one major issue with the code that I overlooked is that it never creates new instances of the dials and resps, which is why you get "null" in runtime errors.

Basically, this snippet is something that I was troubleshooting a few months ago from my old computer, and then I fixed it with the help of forum users, but never fully backed up the fixed version. I apologize for the inconvenience.
In response to Ter13
Ter13 wrote:
> mob
> Old_Man
> verb/talk()
> ShowDial()
> GetDial(src, /Dial/Old_Man/Greet)
>

You made a mistake here. It should be:

> mob
> Old_Man
> verb/talk()
> ShowDial()
> GetDial(usr, /Dial/Old_Man/Greet)
>


You missed the fact that it should also be usr.ShowDial()
In response to D-Cire
D-Cire wrote:
Ter13 wrote:
> > mob
> > Old_Man
> > verb/talk()
> > ShowDial()
> > GetDial(src, /Dial/Old_Man/Greet)
> >

You made a mistake here. It should be:

> > mob
> > Old_Man
> > verb/talk()
> > ShowDial()
> > GetDial(usr, /Dial/Old_Man/Greet)
> >

You missed the fact that it should also be usr.ShowDial()

I thought it was usr. by default?
No, the default scope of instance functions is always src.
In response to Ter13
I think hes more confused as to the difference between src and usr since it's a verb.
In response to D-Cire
D-Cire wrote:
Ter13 wrote:
> > mob
> > Old_Man
> > verb/talk()
> > ShowDial()
> > GetDial(src, /Dial/Old_Man/Greet)
> >

You made a mistake here. It should be:

> > mob
> > Old_Man
> > verb/talk()
> > ShowDial()
> > GetDial(usr, /Dial/Old_Man/Greet)
> >

You missed the fact that it should also be usr.ShowDial()

it still doesn't function
In response to Ter13
Ter13 wrote:
Also, I really don't think you should be using polymorphism as a sort of database.

I'd recommend setting up dialogue trees in another manner:

> dialogue
> var
> list/messages
> New(list/msg)
> messages = msg
> choice
> var
> list/options
> New(list/msg,list/opts)
> options = opts
> . = ..(msg)
>

> var
> list/dialogue_tree = list("someconversation"=new/dialogue(list("message1","message2","message3","message4")),"someconversation2"=new/dialogue/choice(list("message1"),list("choice1","choice2")))
>

> mob
> NPC
> var
> conversation = "someconversation"
>

You can display them however you want, but ultimately, you don't need to assign a type per option. Better to store a series of initialized general conversation objects globally, than to have a type per conversation.

Can you give a better example and is there a way to make it unique to only one NPC instead of making it for all of them
When is this getting fixed?
Bump
Page: 1 2