|
| 1 | +local LEVEL_LOWER = 1 |
| 2 | +local LEVEL_SAME = 2 |
| 3 | +local LEVEL_HIGHER = 3 |
| 4 | + |
| 5 | +local DISTANCE_BESIDE = 1 |
| 6 | +local DISTANCE_CLOSE = 2 |
| 7 | +local DISTANCE_FAR = 3 |
| 8 | +local DISTANCE_VERYFAR = 4 |
| 9 | + |
| 10 | +local directions = { |
| 11 | + [DIRECTION_NORTH] = "north", |
| 12 | + [DIRECTION_SOUTH] = "south", |
| 13 | + [DIRECTION_EAST] = "east", |
| 14 | + [DIRECTION_WEST] = "west", |
| 15 | + [DIRECTION_NORTHEAST] = "north-east", |
| 16 | + [DIRECTION_NORTHWEST] = "north-west", |
| 17 | + [DIRECTION_SOUTHEAST] = "south-east", |
| 18 | + [DIRECTION_SOUTHWEST] = "south-west" |
| 19 | +} |
| 20 | + |
| 21 | +local messages = { |
| 22 | + [DISTANCE_BESIDE] = { |
| 23 | + [LEVEL_LOWER] = "is below you", |
| 24 | + [LEVEL_SAME] = "is standing next to you", |
| 25 | + [LEVEL_HIGHER] = "is above you" |
| 26 | + }, |
| 27 | + [DISTANCE_CLOSE] = { |
| 28 | + [LEVEL_LOWER] = "is on a lower level to the", |
| 29 | + [LEVEL_SAME] = "is to the", |
| 30 | + [LEVEL_HIGHER] = "is on a higher level to the" |
| 31 | + }, |
| 32 | + [DISTANCE_FAR] = "is far to the", |
| 33 | + [DISTANCE_VERYFAR] = "is very far to the" |
| 34 | +} |
| 35 | + |
| 36 | +local spell = Spell("instant") |
| 37 | + |
| 38 | +function spell.onCastSpell(creature, variant) |
| 39 | + local targetId = ForgeMonster:pickClosestFiendish(creature) |
| 40 | + if not targetId then |
| 41 | + creature:sendCancelMessage("No creatures around") |
| 42 | + creature:getPosition():sendMagicEffect(CONST_ME_POFF) |
| 43 | + return false |
| 44 | + end |
| 45 | + local target = Creature(targetId) |
| 46 | + if not target then |
| 47 | + creature:sendCancelMessage("No creatures around") |
| 48 | + creature:getPosition():sendMagicEffect(CONST_ME_POFF) |
| 49 | + return false |
| 50 | + end |
| 51 | + |
| 52 | + local targetPosition = target:getPosition() |
| 53 | + local creaturePosition = creature:getPosition() |
| 54 | + local positionDifference = { |
| 55 | + x = creaturePosition.x - targetPosition.x, |
| 56 | + y = creaturePosition.y - targetPosition.y, |
| 57 | + z = creaturePosition.z - targetPosition.z |
| 58 | + } |
| 59 | + |
| 60 | + local maxPositionDifference, direction = math.max(math.abs(positionDifference.x), math.abs(positionDifference.y)) |
| 61 | + if maxPositionDifference >= 5 then |
| 62 | + local positionTangent = positionDifference.x ~= 0 and positionDifference.y / positionDifference.x or 10 |
| 63 | + if math.abs(positionTangent) < 0.4142 then |
| 64 | + direction = positionDifference.x > 0 and DIRECTION_WEST or DIRECTION_EAST |
| 65 | + elseif math.abs(positionTangent) < 2.4142 then |
| 66 | + direction = positionTangent > 0 and |
| 67 | + (positionDifference.y > 0 and DIRECTION_NORTHWEST or DIRECTION_SOUTHEAST) or |
| 68 | + positionDifference.x > 0 and DIRECTION_SOUTHWEST or DIRECTION_NORTHEAST |
| 69 | + else |
| 70 | + direction = positionDifference.y > 0 and DIRECTION_NORTH or DIRECTION_SOUTH |
| 71 | + end |
| 72 | + end |
| 73 | + |
| 74 | + local level = positionDifference.z > 0 and LEVEL_HIGHER or positionDifference.z < 0 and LEVEL_LOWER or LEVEL_SAME |
| 75 | + local distance = maxPositionDifference < 5 and DISTANCE_BESIDE or maxPositionDifference < 101 and DISTANCE_CLOSE or |
| 76 | + maxPositionDifference < 275 and DISTANCE_FAR or DISTANCE_VERYFAR |
| 77 | + local message = messages[distance][level] or messages[distance] |
| 78 | + if distance ~= DISTANCE_BESIDE then |
| 79 | + message = message .. " " .. directions[direction] |
| 80 | + end |
| 81 | + |
| 82 | + local type = target:getType() |
| 83 | + local stringLevel = 'Unknown' |
| 84 | + if type then |
| 85 | + local bestiaryKillsAmount = type:BestiarytoKill() |
| 86 | + if bestiaryKillsAmount >= 5 and bestiaryKillsAmount <= 25 then |
| 87 | + stringLevel = 'Harmless' |
| 88 | + elseif bestiaryKillsAmount <= 250 then |
| 89 | + stringLevel = 'Trivial' |
| 90 | + elseif bestiaryKillsAmount <= 500 then |
| 91 | + stringLevel = 'Easy' |
| 92 | + elseif bestiaryKillsAmount <= 1000 then |
| 93 | + stringLevel = 'Medium' |
| 94 | + elseif bestiaryKillsAmount <= 2500 then |
| 95 | + stringLevel = 'Hard' |
| 96 | + elseif bestiaryKillsAmount <= 5000 then |
| 97 | + stringLevel = 'Challenging' |
| 98 | + end |
| 99 | + end |
| 100 | + |
| 101 | + message = string.format("The monster " .. message .. ". Be prepared to find a creature of difficulty level \"" .. |
| 102 | + stringLevel .. "\".") |
| 103 | + local timeLeft = math.floor((target:getTimeToChangeFiendish() - os.time()) / 60) |
| 104 | + if (timeLeft <= 15) then |
| 105 | + message = string.format(message .. " " .. ForgeMonster:getTimeLeftToChangeMonster(target)) |
| 106 | + end |
| 107 | + |
| 108 | + creature:sendTextMessage(MESSAGE_INFO_DESCR, message) |
| 109 | + creaturePosition:sendMagicEffect(CONST_ME_MAGIC_BLUE) |
| 110 | + return true |
| 111 | +end |
| 112 | + |
| 113 | +spell:name("Find Fiend") |
| 114 | +spell:words("exiva moe res") |
| 115 | +spell:group("support") |
| 116 | +spell:vocation("druid;true", "elder druid;true", "knight;true", "elite knight;true", "paladin;true", |
| 117 | + "royal paladin;true", "sorcerer;true", "master sorcerer;true") |
| 118 | +spell:id(20) |
| 119 | +spell:cooldown(2 * 1000) |
| 120 | +spell:groupCooldown(2 * 1000) |
| 121 | +spell:level(25) |
| 122 | +spell:mana(20) |
| 123 | +spell:isAggressive(false) |
| 124 | +spell:needLearn(false) |
| 125 | +spell:register() |
0 commit comments