// Helper for output()
	RenderAction(artifact) {
		if (artifact.lastAction.isArcana) {
			const status = artifact.lastAction.rrAbility || null
			return <Table.Cell>
				<ActionLink {...getAction(artifact.lastAction.id)} />
				{status && <img
					src={status.icon}
					className={styles.buffIcon}
					alt={status.name}
				/> }<br/>
				{artifact.lastAction.targetJob &&
					<JobIcon job={JOBS[artifact.lastAction.targetJob]}/>
				}

				{artifact.lastAction.targetName}
			</Table.Cell>
		}
		return <Table.Cell>
			{artifact.lastAction.overrideDBlink &&
				<Fragment>{artifact.lastAction.actionName}</Fragment>
			}
			{!artifact.lastAction.overrideDBlink &&
				<ActionLink {...getAction(artifact.lastAction.id)} />
			}
		</Table.Cell>

	}
Beispiel #2
0
		this.gcds.forEach(gcd => {
			const action = getAction(gcd.actionId)
			this.timeline.addItem(new Item({
				type: 'background',
				start: gcd.timestamp - startTime,
				length: this._getGcdLength(gcd),
				group: 'gcd',
				content: <img src={action.icon} alt={action.name}/>,
			}))
		})
Beispiel #3
0
	_onCast(event) {
		const action = getAction(event.ability.guid)
		//check if Triple window is active
		if (!this._active || action.autoAttack) { return }
		//stop tracking on next GCD after triple is gone
		if (action.onGcd && this._tripleFlag) {
			this._stopRecording()
		} else {
			this._triple.casts.push(event)
		}
	}
Beispiel #4
0
	// Sets the last weaponskill tracker given the damage event
	_setLastWeaponskill(event) {

		this._lastWeaponskill = {
			action: getAction(event.ability.guid),
			damageEvents: [event],
			get id() { return this.action && this.action.id },
			get timestamp() { return this.damageEvents && this.damageEvents[0] && this.damageEvents[0].timestamp },
			get hits() { return this.damageEvents && this.damageEvents.length },
			addDamageEvent(event) { this.damageEvents.push(event) },
		}
	}
Beispiel #5
0
	//saveGcd(event, isInstant) {
	saveGcd(gcdInfo, timestamp) {
		if (!gcdInfo.event) {
			return
		}

		const action = getAction(gcdInfo.event.ability.guid)
		let speedMod = this.speedmod.get(gcdInfo.event.timestamp)
		let castTime = action.castTime

		// HACK NOTE TODO: Need to properly account for abilities that alter only the cast or recast of attacks.
		// Thinking of moving this into a module like speedmod, that can be called with a timestamp to grab modified base castTime/cooldown values
		const HACK_ASTRAL_UMBRAL_SPEED_SCALAR = 0.5
		if (speedMod <= HACK_ASTRAL_UMBRAL_SPEED_SCALAR) {
			speedMod /= HACK_ASTRAL_UMBRAL_SPEED_SCALAR
			castTime *= HACK_ASTRAL_UMBRAL_SPEED_SCALAR
		}

		let isCasterTaxed = false

		// GCD is only to two decimal places, so round it there. Storing in Ms.
		// eslint-disable-next-line no-magic-numbers
		let gcdLength = Math.round((timestamp - gcdInfo.event.timestamp)/10)*10

		if (!gcdInfo.isInstant && castTime >= action.cooldown) {
			gcdLength -= CASTER_TAX
			isCasterTaxed = true
		}

		let normalizedGcd = gcdLength
		if (!gcdInfo.isInstant) {
			normalizedGcd = normalizedGcd * ((BASE_GCD / 1000) / castTime)
		}

		normalizedGcd *= (1 / speedMod)
		normalizedGcd = Math.round(normalizedGcd)

		if (action.id) {
			this.gcds.push({
				timestamp: gcdInfo.event.timestamp,
				length: gcdLength,
				normalizedLength: normalizedGcd,
				speedMod: speedMod,
				castTime: castTime,
				cooldown: action.cooldown,
				casterTaxed: isCasterTaxed,
				actionId: action.id,
				isInstant: gcdInfo.isInstant,
			})
		}
	}
Beispiel #6
0
	_onCast(event) {
		const actionId = event.ability.guid

		// If it's a DWT cast, start tracking
		if (actionId === ACTIONS.DREADWYRM_TRANCE.id) {
			this._startDwt(event.timestamp)
		}

		// Only going to save casts during DWT
		if (!this._active || getAction(actionId).autoAttack) {
			return
		}

		// Save the event to the DWT casts
		this._dwt.casts.push(event)
	}
Beispiel #7
0
	_onCast(event) {
		const action = getAction(event.ability.guid)

		if (!action) {
			return
		}

		// Only include GCDs, but don't double increment either
		if (action.onGcd && !BUFF_CHECK_SKILLS.includes(action)) {
			if (this._lastDragonKickUse[event.targetID]) {
				this._gcdsSinceDK[event.targetID]++
			}

			if (this._lastTwinSnakesUse !== null) {
				this._gcdsSinceTS++
			}
		}
	}
	_onCast(event) {
		const actionId = event.ability.guid

		//check if T3 > F3 happend and if we are in UI and get the MP value at the beginning of your AF
		if (actionId === ACTIONS.FIRE_III.id) {
			if (this._umbralIceStacks === AFUIBUFFMAXSTACK) {
				if (this._T3) {
					this._UIEndingInT3 ++
					this._T3inUIFlag = true
				}
				this._MP = this.combatants.selected.resources.mp
			}
			// If we're gaining AF3 from an F3P, count it as the beginning of the phase for F4 count purposes
			if (this._astralFire !== AFUIBUFFMAXSTACK) {
				if (event.ability.overrideAction) {
					this._atypicalAFStartId = event.ability.overrideAction
				} else {
					this._atypicalAFStartId = ACTIONS.FIRE_III.id
				}
			}
		}

		//If my T3 isn't a proc already and cast under AF, it's straight up wrong.
		if (!event.ability.overrideAction && actionId === ACTIONS.THUNDER_III.id && this._AF > 0) {
			event.ability.overrideAction = ACTIONS.THUNDER_III_FALSE
			this._wrongT3 ++
		}

		//start and stop trigger for our rotations is B3
		if (actionId === ACTIONS.BLIZZARD_III.id) {
			if (!this._first) { this._stopRecording() }
			this._startRecording(event)
		} else if (actionId === ACTIONS.TRANSPOSE.id) {
			this._handleTranspose(event)
		} else if (actionId === ACTIONS.FIRE_III.id && !this._inRotation) {
			// Catch oddly-begun fire phases in case something weird was going on.
			this._startRecording(event)
		}
		if (this._first) { this._first = false }
		if (this._inRotation && !getAction(actionId).autoAttack) {
			this._rotation.casts.push(event)
		}
	}
	_onCast(event) {
		const action = getAction(event.ability.guid)
		if (!action.onGcd) {
			return
		}

		if (action.id === ACTIONS.HEAVY_THRUST.id || this._rotation.current === null) {
			// Heavy Thrust (or the first GCD) is the start of our 11-GCD rotation
			if (this._rotation.current !== null) {
				this._rotation.history.push(this._rotation.current)
			}

			this._rotation.current = {
				start: event.timestamp,
				casts: [],
			}
		}

		this._rotation.current.casts.push(event)
	}
Beispiel #10
0
	_onCast(event) {
		const actionId = event.ability.guid

		if (actionId === ACTIONS.RIDDLE_OF_FIRE.id) {
			this._active = true
			this._riddle = {
				start: event.timestamp,
				end: null,
				casts: [],
			}

			const fightTimeRemaining = this.parser.fight.end_time - event.timestamp
			this._rushing = ROF_DURATION >= fightTimeRemaining
		}

		// we only care about actual skills
		if (!this._active || getAction(actionId).autoAttack) {
			return
		}

		this._riddle.casts.push(event)
	}
Beispiel #11
0
	// Using normalise so the estimate can be used throughout the parse
	normalise(events) {
		for (let i = 0; i < events.length; i++) {
			const event = events[i]

			// Only care about player GCDs
			if (!this.parser.byPlayer(event) || !event.ability) { continue }
			const action = getAction(event.ability.guid)
			if (!action.onGcd) { continue }

			// eslint-disable-next-line default-case
			switch (event.type) {
			// wowa uses beginchannel for this...? need info for flamethrower/that ast skill/passage of arms
			case 'begincast':
				// Can I check for cancels?
				this._castingEvent = event
				break

			case 'cast':
				const hasBeginCast = this._castingEvent !== null && this._castingEvent.ability.guid === action.id
				const relevantEvent = hasBeginCast ? this._castingEvent : event
				this.saveGcd({...this._lastGcd}, relevantEvent.timestamp) // Save last gcd with current timestamp

				this._lastGcd.isInstant = !hasBeginCast
				this._lastGcd.event = relevantEvent

				this._castingEvent = null
				break
			}
		}

		if (events.length) {
			this.saveGcd({...this._lastGcd}, events[events.length - 1].timestamp)
		}
		this._debugLogSavedGcds()

		return events
	}
Beispiel #12
0
	_onCast(event) {
		const action = getAction(event.ability.guid)

		// If the action is an auto, just ignore it
		if (action.autoAttack) {
			return
		}

		// If it's not a GCD, just bump the weave count
		if (this.isOgcd(action)) {
			this._weaves.push(event)
			return
		}

		if (this._ongoingCastEvent && this._ongoingCastEvent.ability.guid === action.id) {
			// This event is the end of a GCD cast
			this._trailingGcdEvent = {
				...event,
				// Override the timestamp of the GCD with when its cast began
				timestamp: this._ongoingCastEvent.timestamp,
			}
		} else {
			// This event was an instant GCD (or log missed the cast starting)
			this._trailingGcdEvent = event
		}

		// Always reset the ongoing cast
		this._ongoingCastEvent = null

		// Throw the current state onto the history
		this._saveIfBad()

		// Reset
		this._leadingGcdEvent = this._trailingGcdEvent
		this._weaves = []
	}
Beispiel #13
0
			rofs.push(riddle.casts.filter(cast => getAction(cast.ability.guid).onGcd).length)
Beispiel #14
0
			const numGcds = riddle.casts.filter(cast => getAction(cast.ability.guid).onGcd).length
Beispiel #15
0
		const gcds = this._riddle.casts.filter(cast => getAction(cast.ability.guid).onGcd)
Beispiel #16
0
				this._overheatWindows.current.gcdCount = this._overheatWindows.current.casts.filter(cast => getAction(cast.ability.guid).onGcd).length
Beispiel #17
0
		const gcds = this._wildfireWindows.current.casts.filter(cast => getAction(cast.ability.guid).onGcd)
Beispiel #18
0
		this.gcds.forEach((gcd) => {
			console.log(this.parser.formatTimestamp(gcd.timestamp) + ' ' + getAction(gcd.actionId).name + '[' + gcd.length +
						'|' + gcd.normalizedLength + '] Speedmod[' + gcd.speedMod + ']' +
						(gcd.isInstant ? ' Instant' : '') + (gcd.casterTaxed ? ' CasterTaxed' : ''))
		})
				const fire3Count = this._rotation.casts.filter(cast => getAction(cast.ability.guid).id === ACTIONS.FIRE_III.id).length
			const hasConvert = this._rotation.casts.filter(cast => getAction(cast.ability.guid).id === ACTIONS.CONVERT.id).length > 0
Beispiel #21
0
			const numGcds = triple.casts.filter(cast => !getAction(cast.ability.guid).onGcd).length
Beispiel #22
0
				.filter(cast =>
					getAction(cast.ability.guid).onGcd &&
					!CORRECT_GCDS.includes(cast.ability.guid)