Pychnight / TshockRpgToolKit

Master Controller for distrubtion of quests, custom npcs, custom items and skills, housing, leveling, npcshops, etc.
GNU General Public License v2.0
11 stars 1 forks source link

[Custom Quests] Kill & Collection Trigger issue #42

Closed Pychnight closed 5 years ago

Pychnight commented 5 years ago

Currently there is a limitation within all triggers that require to be completed within specific amount such as KILL = 10 or Collect 10 of specific types of items.

That issue is you can't send events before the trigger is completed.

tbarela commented 5 years ago

Theres really only 2 ways to go about this, the easy way and the painful way, which is to reengineer the trigger system from the ground up to support stuff like this. Thats wildly out of scope, so we're not going to entertain that one right now.

The easy way involves adding another parameter, that lets you pass in optional method to be executed each time the tally changes. The downside is, these methods are NOT the place to do long running code, or start spawning new triggers, etc. These should do whatever their job is quickly, and nothing else. As a quick example:

The second one has potential to deadlock things. Same with trying to start new triggers there.

Pychnight commented 5 years ago

I would prefer a proper solution to this problem, however as you said it would require refactoring the entire trigger system.

errors already happen during trigger loops if you abort the quest during a loop.

I could deal with the quick solution for now, but I'm also adding this issue to Milestone 4 into the proper solution can be developed.

tbarela commented 5 years ago

GatherItems and KillNpcs triggers now feature have overloads that accept an action( Action<PartyMember,int>, in c# ). The second parameter is the count of whatever was gained( or lost, but the current triggers don't currently use or record losses of any sort, this is for future expansion )

GatherItems Example

def OnTallyChange(member as PartyMember,count as int):
    Broadcast "$(member.Name) gained $count items."

Broadcast "This quest tests the GatherItems trigger."

itemType = "Torch"
itemCount = 5
timeout = 60 * 1000

Delay 3000
Broadcast "Please gather $itemCount $itemType(s)."

result = TriggerWaitAll(timeout,GatherItems(party,OnTallyChange,itemType,itemCount))

if result==true:
    Broadcast "Test is complete!"
    Complete(true)
else:
    Broadcast "Time ran out. Try again."
    Complete(false)

KillNpcs Example

def OnSlimeKilled(member as PartyMember,count as int):
    Broadcast "$(member.Name) killed $count Green Slime(s)!"

party.SendInfoMessage("This quest tests the KillNpcs trigger.")

count = 10

taskSpawner = CreateTask:
    Delay 4000
    party.SendInfoMessage("Generating $count slimes now...")

        #hardcoded to my world...
    tx as Single = 2403
    ty as Single = 263

    for i in range(count):
        Delay 750
        SpawnMob("Green Slime",tx, ty, 5, 1)

taskKill = CreateTask:
    Delay 4000
    party.SendInfoMessage("Kill all the slimes!")

    result = TriggerWaitAll(KillNpcs(party,OnSlimeKilled,count,"Green Slime"))

    if result:
        party.SendInfoMessage("Test is complete!")
        Complete(true)
    else:
        party.SendInfoMessage("You ran out of time. Please try again.")
        Complete(false)

taskSpawner.Start()
taskKill.Start()
taskKill.Wait()

Note that only a single overload exists on each trigger, and it requires you specify all the parameters explicitly. None of the shorter overloads accept the action!

And again -- DO NOT delay or wait on anything in these tally callbacks. Going through a loop is probably fine and spawning things, or running commands is probably okay-- but anything that waits will probably deadlock the quest.