scripts/opposed-wng.js
/**
   * Determines opposed status, sets flags accordingly, creates start/result messages.
   *
   * There's 3 paths handleOpposed can take, either 1. Responding to being targeted, 2. Starting an opposed test, or neither.
   *
   * 1. Responding to a target: If the actor has a value in flags.oppose, that means another actor targeted them: Organize
   *    attacker and defender data, and send it to the OpposedWNG.evaluateOpposedTest() method. Afterward, remove the oppose
   *    flag
   * 2. Starting an opposed test: If the user using the actor has a target, start an opposed Test: create the message then
   *    insert oppose data into the target's flags.oppose object.
   * 3. Neither: If no data in the actor's oppose flags, and no targets, skip everything and return.
   *
   *
   * @param {Object} message    The message created by the override (see above) - this message is the Test result message.
   */
Determines opposed status, sets flags accordingly, creates start/result messages.
There's 3 paths handleOpposed can take, either 1. Responding to being targeted, 2. Starting an opposed test, or neither.

1. Responding to a target: If the actor has a value in flags.oppose, that means another actor targeted them: Organize
attacker and defender data, and send it to the OpposedWNG.evaluateOpposedTest() method. Afterward, remove the oppose
flag
2. Starting an opposed test: If the user using the actor has a target, start an opposed Test: create the message then
insert oppose data into the target's flags.oppose object.
3. Neither: If no data in the actor's oppose flags, and no targets, skip everything and return.

@param {Object} message    The message created by the override  - this message is the Test result message.
Determines opposed status sets flags accordingly creates start / result messages . There ' s 3 paths handleOpposed can take either 1 . Responding to being targeted 2 . Starting an opposed test or neither . 1 . Responding to a target : If the actor has a value in flags . oppose that means another actor targeted them : Organize attacker and defender data and send it to the OpposedWNG . evaluateOpposedTest () method . Afterward remove the oppose flag 2 . Starting an opposed test : If the user using the actor has a target start an opposed Test : create the message then insert oppose data into the target ' s flags . oppose object . 3 . Neither : If no data in the actor ' s oppose flags and no targets skip everything and return . @param { Object } message The message created by the override - this message is the Test result message .
static async handleOpposedTarget(message)
  {
    if (!message) return;
    let actor = WNG_Utility.getSpeaker(message.data.speaker)
    let testResult = message.data.flags.data.postData
    try
    {
      if (actor.data.flags.oppose) 
      { 
        let attackMessage = game.messages.get(actor.data.flags.oppose.messageId) 
        let attacker = {
          speaker: actor.data.flags.oppose.speaker,
          testResult: attackMessage.data.flags.data.postData,
          img: WNG_Utility.getSpeaker(actor.data.flags.oppose.speaker).data.img
        }
        let defender = {
          speaker: message.data.speaker,
          testResult: testResult,
          img: actor.data.msg
        } 
        await OpposedWNG.evaluateOpposedTest(attacker, defender,
        {
          target: true,
          startMessageId: actor.data.flags.oppose.startMessageId
        })
        await actor.update(
        {
          "-=flags.oppose": null
        }) 
      }
      else if (game.user.targets.size) 
      {
        let attacker;
        if (message.data.speaker.token)
          attacker = canvas.tokens.get(message.data.speaker.token).data
        else 
          attacker = actor.data.token
        game.user.targets.forEach(async target =>
        {
          let content =
            `<div class ="opposed-message">
            <b>${attacker.name}</b> ${game.i18n.localize("ROLL.Targeting")} <b>${target.data.name}</b>
          </div>
          <div class = "opposed-tokens">
          <div class = "attacker"><img src="${attacker.img}" width="50" height="50"/></div>
          <div class = "defender"><img src="${target.data.img}" width="50" height="50"/></div>
          </div>
          <div class="unopposed-button" data-target="true" title="${game.i18n.localize("Unopposed")}"><a><i class="fas fa-arrow-down"></i></a></div>`
          let startMessage = await ChatMessage.create(
          {
            user: game.user._id,
            content: content,
            speaker: message.data.speaker,
            ["flags.unopposeData"]: 
            {
              attackMessageId: message.data._id,
              targetSpeaker:
              {
                scene: target.scene.data._id,
                token: target.data._id,
                scene: target.actor.data._id,
                alias: target.data.name
              }
            }
          })
        if (!game.user.isGM)
        {
          game.socket.emit("system.wng", {
            type: "target",
            payload: {
              target: target.data._id,
              scene: canvas.scene.id,
              opposeFlag : {
                speaker: message.data.speaker,
                messageId: message.data._id,
                startMessageId: startMessage.data._id
              }
            }
          })
        }
        else
        {
          target.actor.update(
          {
            "flags.oppose":
            {
              speaker: message.data.speaker,
              messageId: message.data._id,
              startMessageId: startMessage.data._id
            }
          })
        }
          target.setTarget(false);
        })
      }
    }
    catch
    {
      await actor.update({"-=flags.oppose": null}) 
    }
  }
static async handleOpposedTarget ( message ) { if ( ! message ) return ; let actor = WNG_Utility . getSpeaker ( message . data . speaker ) let testResult = message . data . flags . data . postData try { if ( actor . data . flags . oppose ) { let attackMessage = game . messages . get ( actor . data . flags . oppose . messageId ) let attacker = { speaker : actor . data . flags . oppose . speaker , testResult : attackMessage . data . flags . data . postData , img : WNG_Utility . getSpeaker ( actor . data . flags . oppose . speaker ) . data . img } let defender = { speaker : message . data . speaker , testResult : testResult , img : actor . data . msg } await OpposedWNG . evaluateOpposedTest ( attacker , defender , { target : true , startMessageId : actor . data . flags . oppose . startMessageId } ) await actor . update ( { "-=flags.oppose" : null } ) } else if ( game . user . targets . size ) { let attacker ; if ( message . data . speaker . token ) attacker = canvas . tokens . get ( message . data . speaker . token ) . data else attacker = actor . data . token game . user . targets . forEach ( async target => { let content = ` ${ attacker . name } ${ game . i18n . localize ( "ROLL.Targeting" ) } ${ target . data . name } ${ attacker . img } ${ target . data . img } ${ game . i18n . localize ( "Unopposed" ) } ` let startMessage = await ChatMessage . create ( { user : game . user . _id , content : content , speaker : message . data . speaker , [ "flags.unopposeData" ] : { attackMessageId : message . data . _id , targetSpeaker : { scene : target . scene . data . _id , token : target . data . _id , scene : target . actor . data . _id , alias : target . data . name } } } ) if ( ! game . user . isGM ) { game . socket . emit ( "system.wng" , { type : "target" , payload : { target : target . data . _id , scene : canvas . scene . id , opposeFlag : { speaker : message . data . speaker , messageId : message . data . _id , startMessageId : startMessage . data . _id } } } ) } else { target . actor . update ( { "flags.oppose" : { speaker : message . data . speaker , messageId : message . data . _id , startMessageId : startMessage . data . _id } } ) } target . setTarget ( false ) ; } ) } } catch { await actor . update ( { "-=flags.oppose" : null } ) } }
Determines opposed status, sets flags accordingly, creates start/result messages.
Determines opposed status sets flags accordingly creates start / result messages .
// Get actor/tokens and test results /* -------------- IF OPPOSING AFTER BEING TARGETED -------------- */ // If someone targets an actor, they insert data in the target's flags.oppose // So if data exists here, this actor has been targeted, see below for what kind of data is stored here // Retrieve attacker's test result message // Organize attacker/defender data // evaluateOpposedTest is usually for manual opposed tests, it requires extra options for targeted opposed test // After opposing, remove oppose /* -------------- IF TARGETING SOMEONE -------------- */ // if user using the actor has targets // If token data was found in the message speaker (see setupCardOptions) // If no token data was found in the speaker, use the actor's token data instead // For each target, create a message, and insert oppose data in the targets' flags // Create the Opposed starting message // Optional data to resolve unopposed tests - used for damage values // Add oppose data flag to the target // Remove current targets // If something went wrong, remove incoming opposed tests