Weather events #123


  • Accepted
Open
  • _ForgeUser228323 created this issue Aug 5, 2010
    Author

    OK, this is a little out there, and will only appeal to roleplayers, but I think it's cool. >.>

    The following events would be registered:
    -Enter zone/subzone
    -Leave zone/subzone
    -Going inside
    -An intermittent timer not tied to an in-game event

    However, while each of these could have their cooldown and chance to fire set as normal, the phrases would be further categorized by the climate of the zone/subzone. For instance:
    Enter a -cold- zone: /e pulls on a scarf and some earmuffs
    Leave a -windy- zone: /e tries to fix her wind-blown hair
    Go inside in a -hot-zone: /e is glad to get a respite from the heat
    Intermittently in a -swampy- zone: /e swats a mosquito on her arm

    Because the appeal of this would be relatively limited, it would be created as a separate module that is turned off by default and loaded on demand.

  • _ForgeUser228323 added the tags New Enhancment Aug 5, 2010
  • rismisner posted a comment Aug 6, 2010

    I think this is a great idea, but tricky...

    This reminds me of ticket 110 "Conditions for /ss makro" which proposed a similar differentiation of macros for time of day, that struck me with the same kind of data format and UI design questions as the climate of the zone. More thoughts captured here: http://www.wowace.com/addons/speakinspell/tickets/110-conditions-for-ss-makro/

    Are you suggesting additional event hooks? Following the current event key string paradigm, this could simply be 4 new event triggers for 4 types of zones. But that really pushes the extensibility of the already-too-long event list. I think if we consider both of the ideas in ticket 110 and this one, we should be able to come up with a design that fits within one event (changed zone) and encapsulates options inside that event trigger (EventTableEntry ete) for how the event should be announced based on the climate of the new zone (or re: ticket 110, the time of day)

    Or, well... SS 3.3.5.xx currently supports "changed zone" and "changed subzone" event triggers which occur once when you simultaneously leave one zone and enter another. (it's 1 event, not 2)

    Anyway my overall point is that the challenges of ticket 110 and this one both push hard against the limitations of the current event key string list design, which needs work to be able to support these ideas (and more)

  • rismisner removed a tag New Aug 6, 2010
  • rismisner added a tag Accepted Aug 6, 2010
  • _ForgeUser228323 posted a comment Aug 7, 2010

    OK, here's a little pseudocode to kind of illustrate what I'm thinking better. I know I'm not using the right names of functions or whatever, but hopefully you can follow my thought process.

    BZ=LibBabbleZone
    BSZ=LibBabbleSubZone
    Speakinspell.Climates = {
    [BSZ["Bronze Dragonshrine"]={"windy","desert"},
    [BZ["Dragonblight"]] = {"cold","snowy","windy"},
    [BZ["Stranglethorn"]] = {"hot","humid"},
    [BZ["Swamp of Sorrows"]] = {"humid"},
    [BZ["Tanaris"]]={"hot","desert"}
    }
    
    function Speakinspell:ZONE_CHANGED () 
    local oldClimateList = Speakinspell.Climates[oldZone]
    if Speakinspell.Climates[GetSubZoneText()] then
       local climateList = Speakinspell.Climates[GetSubZoneText()]
       oldZone=GetSubZoneText()
    else
       local climateList = Speakinspell.Climates[GetZoneText()]
       oldZone=GetZoneText()
    end
    local phrasetable={}
      for (k,v) in ipairs(climateList)
      --The function would find Enter Zone texts for each climate that the zone has listed
       phrasetable+=GetPhrases("ENTER_ZONE_"..strupper(v))
      end
      for (k,v) in ipairs(oldClimateList)
        --The function would find Leave Zone texts for each climate the old zone has listed
       phrasetable+=GetPhrases("LEAVE_ZONE_"..strupper(v))
      end
      Speakinspell:Pickaphrase(Phrasetable)
    end
    

    User interface would be like for spells, where you have 4 potential events associated with each spell name.
    When I enter a cold zone (creates ENTER_ZONE_COLD ete)
    When I leave a cold zone (creates LEAVE_ZONE_COLD ete)
    Intermittently in a cold zone (creates INTERMITTENT_COLD ete)
    (going inside is not going to be as easy as I thought, so just nix it)

    What do you think?

  • rismisner posted a comment Aug 10, 2010

    I feel like this post needs editing, but meh... I'm just going to ramble off my train of thought about all the related issues and possible paths we could take to resolve those issues in hopes that we can brainstorm the best possible approach...

    The pseudo-code that you posted strikes me as the ideal way to implement something like this... Unfortunately, the current architecture of the system won't allow for building a list of speeches like that. The current design wants you to do it like this:

    for (k,v) in ipairs(climateList)
      --The function would find Enter Zone texts for each climate that the zone has listed
       local destub = {
          name = v,
          type = "CLIMATE_ENTER_ZONE", --new event type
       }
       SpeakinSpell:OnSpeechEvent(destub)
    end
    for (k,v) in ipairs(oldClimateList)
       --The function would find Enter Zone texts for each climate that the zone has listed
       local destub = {
          name = v,
          type = "CLIMATE_LEAVE_ZONE", --new event type
       }
       SpeakinSpell:OnSpeechEvent(destub)
    end
    

    Unfortunately, that would fire many events simultaneously, instead of bundling up all of those separate EventTableEntry.Messages tables, and picking one speech from all possible applicants... You might get many results, or you would get the first applicable climate type listed in the Speakinspell.Climates table, and the rest would be silenced by the global cooldown.

    There's a problem with doing something like this to build up a combined list of speeches to choose from...

    local phrasetable = {}
    phrasetable += EventTable["ENTER_ZONE_"..strupper(v)].Messages
    phrasetable += EventTable["LEAVE_ZONE_"..strupper(v)].Messages
    local msg = self:GetRandomTableEntry(phrasetable)
    self:SayOneLine(msg)
    

    The problem is that the EventTableEntry for each of these events can have different options for the cooldown, random chance, expand sub-macro calls, "go in order" (coming soon), etc, etc. There are a lot of options beyond the speech list in the Messages table.

    This is a problem for a wide variety of event triggers or similar functions that I'd like to create. There are a wide variety of approaches we could take to either redesign this idea to fit the current architecture, and/or redesign the architecture to support a wider variety of ideas...

    Hmm... what if we created a function as an alternative to OnSpeechEvent(stub) ... OnMultipleSpeechEvents( stublist ) ... we'd call into it something like this...

    function Speakinspell:ZONE_CHANGED () 
    local oldClimateList = Speakinspell.Climates[oldZone]
    if Speakinspell.Climates[GetSubZoneText()] then
       local climateList = Speakinspell.Climates[GetSubZoneText()]
       oldZone=GetSubZoneText()
    else
       local climateList = Speakinspell.Climates[GetZoneText()]
       oldZone=GetZoneText()
    end
    local destublist={}
      for (k,climate) in ipairs(climateList)
      --The function would find Enter Zone texts for each climate that the zone has listed
       local destub = {
          type = "CLIMATE",
          name = "Enter " .. strupper(climate),
       }
       tinsert(destublist, destub)
      end
      for (k,v) in ipairs(oldClimateList)
       local destub = {
          type = "CLIMATE",
          name = "Leave " .. strupper(climate),
       }
       tinsert(destublist, destub)
      end
      Speakinspell:OnMultipleSpeechEvents( destublist )
    end
    
    function SpeakinSpell:OnMultipleSpeechEvents( destublist )
      -- just listing pseudo-code steps here that would have to happen
      -- validate the destubs into full DetectedEvent objects
      -- find the associated EventTableEntry (ete) data for each DetectedEvent
      -- the tricky part: somehow combine the options in that list of etes
      -- that's easy for the Messages tables, but not so obvious how to handle it for
      -- cooldown, random chance, selected chat channel, etc.
      -- but the purpose of this function would be to resolve those potentially conflicting options
    end
    

    Alternatively... I dunno... maybe the GUI could support a way to link these EventTableEntries together, in order to force them to share the same options? So for example if you changed the cooldown on "When I enter a cold zone" that would automatically set the same cooldown on "When I leave a hot zone" so that there can't ever be a conflict among the settings. Given some concept of linked event triggers like this, would that be hard-coded for these special events, or is there a way to make that a user-configurable feature for users to link other events together in the same way?

    There is another train of thought I've considered before, to separate the speech lists from the event triggers. In effect, the idea here would be to remove the Messages table from the EventTableEntry (ete). ete.Messages would be replaced by ete.MessageLists ... instead of listing the actual speeches, the ete.MessageLists would list the names (or IDs) of (shared) speech lists. Those shared speech lists would always be combined, the list flattened (for a single RNG) and then a random speech selected from the combined, flattened list of actual macros. I got to thinking along these lines re: mounts, because that's basically how I have currently set up mounts via /ss macro calls. This architecture change would basically force all event triggers to make one or more /ss macro calls into shared speech lists. Then I can see a design like that more easily supporting an idea like this one... especially if you enhance the event trigger to attach options to each speech list re: which speech lists can be used under which conditions. Follow all that?

    The simpler, short-term approach would be to simply allow this feature to fire off many separate events, which remain isolated from each other. Give each event a low enough random chance (something like 5%), and maintain an overall global cooldown >= 2 seconds or so, and then if we move from swamp of sorrows to the blasted lands, we would fire off many events simultaneously:

    • leave wet zone
    • leave humid zone
    • enter hot zone
    • enter desert zone

    Those events would be unaware of each other, their speech lists would not be combined, and you'd have a multiple RNG situation. Assuming the events fired in that order, and each has a 5% chance to announce... you'd have a 5% chance to announce leaving a wet zone, and if you announced that, the rest would be silenced by the GCD. Fail the chance to announce leaving a wet zone, and you have a 5% chance to announce leaving a humid zone, and if we pick that, it sets the GCD to silence the rest... and so on.

    That simpler approach would work within the current architecture, but I'd have 2 gripes with it:

    1. A single RNG has better results than a multiple RNG. In my example, enter desert zone has a lower net chance to be announced than leaving a wet zone, just because we hit it last in the for loop, and have been rolling the dice many times (instead of once)
    2. NewEventsDetected would have to grow to support all possible permutations of entering and leaving each climate, which is do-able, but continues to eat more and more memory, and grows into something less and less maintainable. Even outside the scope of this ticket, NewEventsDetected needs to go away, and be replaced by other concepts, or be redesigned in some way.

    In all my rambling and thinking out loud about it here, my favorite idea at the moment is OnMultipleSpeechEvents. I think it would apply nicely to mounts and pets too, for example when summoning my violet proto drake, I would simultaneously trigger multiple speech events for:

    1. summoned an animal (a mount or pet)
    2. summoned a mount
    3. summoned a flying mount
    4. summoned a fast flying mount
    5. summoned a specific mount by name

    OnMultipleSpeechEvents would decide which event triggers apply, which are on CD, merge any other event-specific options, merge the speech lists, do a single RNG to pick a speech from the combined list, and then say it. That's basically what I do with mounts already, but in a somewhat arcane way by stretching the /ss macro feature.

    In all my rambling here, do you see the problem I'm getting at? Do you have any better way in mind to conceptualize it? I'm looking at it mostly from the bottom up... how should it look from the top down? Thinking about it starting at the GUI for setting this up, and then going down from there into the implementation may reveal some better way to think about it inside the engine - i.e. the same way the end-user is going to naturally assume it works.


To post a comment, please login or register a new account.