Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2023-07-04 10:05:31 +08:00
59 changed files with 1562 additions and 845 deletions
+7
View File
@@ -0,0 +1,7 @@
# Used by "mix format"
[
inputs: [
".formatter.exs",
"account.exs"
]
]
+10
View File
@@ -0,0 +1,10 @@
FROM elixir:1.14-slim
RUN mix local.hex --force && \
mix local.rebar --force
COPY account.exs /account.exs
COPY srp.exs /srp.exs
RUN chmod +x /account.exs
CMD /account.exs
+102
View File
@@ -0,0 +1,102 @@
# Account.exs
Simple script to create an account for AzerothCore
This script allows a server admin to create a user automatically when after the `dbimport` tool runs, without needed to open up the `worldserver` console.
## How To Use
### Pre-requisites
- MySQL is running
- The authserver database (`acore_auth`, typically) has a table named `account`
### Running
```bash
$ elixir account.exs
```
### Configuration
This script reads from environment variables in order to control which account it creates and the MySQL server it's communicating with
- `ACORE_USERNAME` Username for account, default "admin"
- `ACORE_PASSWORD` Password for account, default "admin"
- `ACORE_GM_LEVEL` GM Level for account, default 3
- `MYSQL_DATABASE` Database name, default "acore_auth"
- `MYSQL_USERNAME` MySQL username, default "root"
- `MYSQL_PASSWORD` MySQL password, default "password"
- `MYSQL_PORT` MySQL Port, default 3306
- `MYSQL_HOST` MySQL Host, default "localhost"
To use these environment variables, execute the script like so:
```bash
$ MYSQL_HOST=mysql \
MYSQL_PASSWORD="fourthehoard" \
ACORE_USERNAME=drekthar \
ACORE_PASSWORD=securepass22 \
elixir account.exs
```
This can also be used in a loop. Consider this csv file:
```csv
user,pass,gm_level
admin,adminpass,2
soapuser,soappass,3
mainuser,userpass,0
```
You can then loop over this csv file, and manage users like so:
```bash
$ while IFS=, read -r user pass gm; do
ACORE_USERNAME=$user \
ACORE_PASSWORD=$pass \
GM_LEVEL=$gm \
elixir account.exs
done <<< $(tail -n '+2' users.csv)
```
### Docker
Running and building with docker is simple:
```bash
$ docker build -t acore/account-create .
$ docker run \
-e MYSQL_HOST=mysql \
-v mix_cache:/root/.cache/mix/installs \
acore/account-create
```
Note that the `MYSQL_HOST` is required to be set with the docker container, as the default setting targets `localhost`.
### docker-compose
A simple way to integrate this into a docker-compose file.
This is why I wrote this script - an automatic way to have an admin account idempotently created on startup of the server.
```yaml
services:
account-create:
image: acore/account-create:${DOCKER_IMAGE_TAG:-master}
build:
context: apps/account-create/
dockerfile: apps/account-create/Dockerfile
environment:
MYSQL_HOST: ac-database
MYSQL_PASSWORD: ${DOCKER_DB_ROOT_PASSWORD:-password}
ACORE_USERNAME: ${ACORE_ROOT_ADMIN_ACCOUNT:-admin}
ACORE_PASSWORD: ${ACORE_ROOT_ADMIN_PASSWORD:-password}
volumes:
- mix_cache:/root/.cache/mix/installs
profiles: [local, app, db-import-local]
depends_on:
ac-db-import:
condition: service_completed_successfully
```
+134
View File
@@ -0,0 +1,134 @@
#!/usr/bin/env elixir
# Execute this Elixir script with the below command
#
# $ ACORE_USERNAME=foo ACORE_PASSWORD=barbaz123 elixir account.exs
#
# Set environment variables for basic configuration
#
# ACORE_USERNAME - Username for account, default "admin"
# ACORE_PASSWORD - Password for account, default "admin"
# ACORE_GM_LEVEL - GM level for account
# MYSQL_DATABASE - Database name, default "acore_auth"
# MYSQL_USERNAME - MySQL username, default "root"
# MYSQL_PASSWORD - MySQL password, default "password"
# MYSQL_PORT - MySQL Port, default 3306
# MYSQL_HOST - MySQL Host, default "localhost"
# Install remote dependencies
[
{:myxql, "~> 0.6.0"}
]
|> Mix.install()
# Start the logger
Application.start(:logger)
require Logger
# Constants
default_credential = "admin"
default_gm_level = "3"
account_access_comment = "Managed via account-create script"
# Import srp functions
Code.require_file("srp.exs", Path.absname(__DIR__))
# Assume operator provided a "human-readable" name.
# The database stores usernames in all caps
username_lower =
System.get_env("ACORE_USERNAME", default_credential)
|> tap(&Logger.info("Account to create: #{&1}"))
username = String.upcase(username_lower)
password = System.get_env("ACORE_PASSWORD", default_credential)
gm_level = System.get_env("ACORE_GM_LEVEL", default_gm_level) |> String.to_integer()
if Range.new(0, 3) |> Enum.member?(gm_level) |> Kernel.not do
Logger.info("Valid ACORE_GM_LEVEL values are 0, 1, 2, and 3. The given value was: #{gm_level}.")
end
{:ok, pid} =
MyXQL.start_link(
protocol: :tcp,
database: System.get_env("MYSQL_DATABASE", "acore_auth"),
username: System.get_env("MYSQL_USERNAME", "root"),
password: System.get_env("MYSQL_PASSWORD", "password"),
port: System.get_env("MYSQL_PORT", "3306") |> String.to_integer(),
hostname: System.get_env("MYSQL_HOST", "localhost")
)
Logger.info("MySQL connection created")
Logger.info("Checking database for user #{username_lower}")
# Check if user already exists in database
{:ok, result} = MyXQL.query(pid, "SELECT salt FROM account WHERE username=?", [username])
%{salt: salt, verifier: verifier} =
case result do
%{rows: [[salt | _] | _]} ->
Logger.info("Salt for #{username_lower} found in database")
# re-use the salt if the user exists in database
Srp.generate_stored_values(username, password, salt)
_ ->
Logger.info("Salt not found in database for #{username_lower}. Generating a new one")
Srp.generate_stored_values(username, password)
end
Logger.info("New salt and verifier generated")
# Insert values into DB, replacing the verifier if the user already exists
result =
MyXQL.query(
pid,
"""
INSERT INTO account
(`username`, `salt`, `verifier`)
VALUES
(?, ?, ?)
ON DUPLICATE KEY UPDATE verifier=?
""",
[username, salt, verifier, verifier]
)
case result do
{:error, %{message: message}} ->
File.write("fail.log", message)
Logger.info(
"Account #{username_lower} failed to create. You can check the error message at fail.log."
)
exit({:shutdown, 1})
# if num_rows changed and last_insert_id == 0, it means the verifier matched. No change necessary
{:ok, %{num_rows: 1, last_insert_id: 0}} ->
Logger.info(
"Account #{username_lower} doesn't need to have its' password changed. You should be able to log in with that account"
)
{:ok, %{num_rows: 1}} ->
Logger.info(
"Account #{username_lower} has been created. You should now be able to login with that account"
)
{:ok, %{num_rows: 2}} ->
Logger.info(
"Account #{username_lower} has had its' password reset. You should now be able to login with that account"
)
end
# Set GM level to configured value
{:ok, _} =
MyXQL.query(
pid,
"""
INSERT INTO account_access
(`id`, `gmlevel`, `comment`)
VALUES
((SELECT id FROM account WHERE username=?), ?, ?)
ON DUPLICATE KEY UPDATE gmlevel=?, comment=?
""", [username, gm_level, account_access_comment, gm_level, account_access_comment])
Logger.info("GM Level for #{username_lower} set to #{gm_level}")
+59
View File
@@ -0,0 +1,59 @@
defmodule Srp do
# Constants required in WoW's SRP6 implementation
@n <<137, 75, 100, 94, 137, 225, 83, 91, 189, 173, 91, 139, 41, 6, 80, 83, 8, 1, 177, 142, 191,
191, 94, 143, 171, 60, 130, 135, 42, 62, 155, 183>>
@g <<7>>
@field_length 32
# Wrapper function
def generate_stored_values(username, password, salt \\ "") do
default_state()
|> generate_salt(salt)
|> calculate_x(username, password)
|> calculate_v()
end
def default_state() do
%{n: @n, g: @g}
end
# Generate salt if it's not defined
def generate_salt(state, "") do
salt = :crypto.strong_rand_bytes(32)
Map.merge(state, %{salt: salt})
end
# Don't generate salt if it's already defined
def generate_salt(state, salt) do
padded_salt = pad_binary(salt)
Map.merge(state, %{salt: padded_salt})
end
# Get h1
def calculate_x(state, username, password) do
hash = :crypto.hash(:sha, String.upcase(username) <> ":" <> String.upcase(password))
x = reverse(:crypto.hash(:sha, state.salt <> hash))
Map.merge(state, %{x: x, username: username})
end
# Get h2
def calculate_v(state) do
verifier =
:crypto.mod_pow(state.g, state.x, state.n)
|> reverse()
|> pad_binary()
Map.merge(state, %{verifier: verifier})
end
defp pad_binary(blob) do
pad = @field_length - byte_size(blob)
<<blob::binary, 0::pad*8>>
end
defp reverse(binary) do
binary
|> :binary.decode_unsigned(:big)
|> :binary.encode_unsigned(:little)
end
end
@@ -0,0 +1,5 @@
-- DB update 2023_06_21_00 -> 2023_06_22_00
--
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_murmur_touch', 'spell_shockwave_knockback');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(33686, 'spell_shockwave_knockback');
@@ -0,0 +1,4 @@
-- DB update 2023_06_22_00 -> 2023_06_23_00
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 818) AND (`source_type` = 0) AND (`id` IN (2));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(818, 0, 2, 0, 23, 0, 100, 0, 12544, 0, 10000, 10000, 0, 11, 12544, 64, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Mai\'Zoth - On Aura \'Frost Armor\' Missing - Cast \'Frost Armor\'');
@@ -0,0 +1,7 @@
-- DB update 2023_06_23_00 -> 2023_06_23_01
UPDATE `creature` SET `MovementType` = 2 WHERE `guid` IN (6974,6989,7210) AND `id1` IN (2718,2717,2907);
DELETE FROM `creature_addon` WHERE (`guid` IN (6974,6989,7210));
INSERT INTO `creature_addon` (`guid`, `path_id`, `bytes2`) VALUES
(6974, 69740, 1),
(6989, 69890, 1),
(7210, 72100, 1);
@@ -0,0 +1,5 @@
-- DB update 2023_06_23_01 -> 2023_06_24_00
--
UPDATE `smart_scripts` SET `action_param2`=0 WHERE `entryorguid`=1651800 AND `source_type`=9 AND `id` IN (2, 6);
UPDATE `creature_template` SET `faction`=7 WHERE `entry`=16534;
@@ -0,0 +1,3 @@
-- DB update 2023_06_24_00 -> 2023_06_24_01
-- Add extra flag 33554432 to several skeleton creatures in Auchenai Crypts to avoid chain pulling
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|33554432 WHERE (`entry` IN (18700, 20317, 18521, 20315, 18524, 20298));
@@ -0,0 +1,28 @@
-- DB update 2023_06_24_01 -> 2023_06_24_02
--
DELETE FROM `npc_trainer` WHERE `SpellID` IN (
39973, -- Frost Grenades
40274, -- Furious Gizmatic Goggles
41311, -- Justicebringer 2000 Specs
41312, -- Tankatronic Goggles
41314, -- Surestrike Goggles v2.0
41315, -- Gadgetstorm Goggles
41316, -- Living Replicator Specs
41317, -- Deathblow X11 Goggles
41318, -- Wonderheal XT40 Shades
41319, -- Magnified Moon Specs
41320, -- Destruction Holo-gogs
41321 -- Powerheal 4000 Lens
);
INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`, `ReqSpell`) VALUES
(201013, 39973, 50000, 202, 335, 0, 0),
(201013, 40274, 50000, 202, 350, 0, 0),
(201013, 41311, 50000, 202, 350, 0, 0),
(201013, 41312, 50000, 202, 350, 0, 0),
(201013, 41314, 50000, 202, 350, 0, 0),
(201013, 41315, 50000, 202, 350, 0, 0),
(201013, 41316, 50000, 202, 350, 0, 0),
(201013, 41317, 50000, 202, 350, 0, 0),
(201013, 41318, 50000, 202, 350, 0, 0),
(201013, 41319, 50000, 202, 350, 0, 0),
(201013, 41320, 50000, 202, 350, 0, 0);
@@ -0,0 +1,6 @@
-- DB update 2023_06_24_02 -> 2023_06_24_03
--
DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_capacitus_polarity_charge_aura';
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(39088, 'spell_capacitus_polarity_charge_aura'),
(39091, 'spell_capacitus_polarity_charge_aura');
@@ -0,0 +1,4 @@
-- DB update 2023_06_24_03 -> 2023_06_24_04
DELETE FROM `npc_trainer` WHERE `SpellID` = 41321;
INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`, `ReqSpell`) VALUES
(201013, 41321, 50000, 202, 350, 0, 0);
@@ -0,0 +1,3 @@
-- DB update 2023_06_24_04 -> 2023_06_24_05
--
UPDATE `creature_template` SET `ScriptName` = '' WHERE `ScriptName` = 'npc_ahune_frozen_core';
@@ -0,0 +1,3 @@
-- DB update 2023_06_24_05 -> 2023_06_24_06
--
UPDATE `creature_template` SET `ScriptName` = '' WHERE (`entry` = 16592);
@@ -0,0 +1,42 @@
-- DB update 2023_06_24_06 -> 2023_06_26_00
-- Shay Leafrunner - On Quest - Wandering Shay --
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE (`entry` = 7774);
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 7774);
INSERT INTO `smart_scripts` VALUES
(7774, 0, 0, 0, 19, 0, 100, 0, 2845, 0, 0, 0, 0, 80, 777400, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Quest \'Wandering Shay\' Taken - Run Script'),
(7774, 0, 1, 0, 8, 0, 100, 0, 11402, 0, 0, 0, 0, 80, 777401, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Spellhit \'Shay`s Bell\' - Run Script'),
(7774, 0, 2, 0, 75, 0, 100, 0, 0, 7765, 7, 10000, 0, 80, 777402, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Distance To Creature - Run Script'),
(7774, 0, 3, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 80, 777403, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Just Died - Run Script'),
(7774, 0, 4, 0, 38, 0, 100, 0, 1, 1, 0, 0, 0, 67, 61, 30000, 35000, 60000, 65000, 100, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Data Set 1 1 - Create Timed Event'),
(7774, 0, 5, 6, 59, 0, 100, 0, 61, 0, 0, 0, 0, 73, 38, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Timed Event 61 Triggered - Trigger Timed Event 38'),
(7774, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Timed Event 61 Triggered - Stop Follow '),
(7774, 0, 7, 8, 61, 0, 100, 0, 0, 0, 0, 0, 0, 89, 15, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Data Set 1 1 - Start Random Movement'),
(7774, 0, 8, 9, 61, 0, 100, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Data Set 1 1 - Say Line 2'),
(7774, 0, 9, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Data Set 1 1 - Say Line 3'),
(7774, 0, 10, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 74, 61, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Respawn - Remove Timed Event 61'),
(7774, 0, 11, 0, 6, 0, 100, 0, 0, 0, 0, 0, 0, 6, 2845, 0, 0, 0, 0, 0, 18, 10, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Just Died - Fail Quest \'Wandering Shay\''),
(7774, 0, 12, 0, 75, 0, 100, 1, 0, 7765, 10, 5000, 0, 1, 0, 0, 0, 0, 0, 0, 11, 7765, 10, 1, 0, 0, 0, 0, 0, 'Shay Leafrunner - On Distance To Creature - Say Line 0');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 777400);
INSERT INTO `smart_scripts` VALUES
(777400, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Remove Flags Immune To Players & Immune To NPC\'s'),
(777400, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 29, 2, 3, 7765, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Start Follow Invoker'),
(777400, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Say Line 0'),
(777400, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Set Data 1 1');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 777401);
INSERT INTO `smart_scripts` VALUES
(777401, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 29, 2, 3, 7765, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Start Follow Invoker'),
(777401, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Say Line 1');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 777402);
INSERT INTO `smart_scripts` VALUES
(777402, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 15, 2845, 0, 0, 0, 0, 0, 18, 10, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Quest Credit \'Wandering Shay\''),
(777402, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Say Line 4');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 777403);
INSERT INTO `smart_scripts` VALUES
(777403, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 6, 2845, 0, 0, 0, 0, 0, 18, 10, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Fail Quest \'Wandering Shay\''),
(777403, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Set Flags Immune To Players & Immune To NPC\'s'),
(777403, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 74, 61, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Shay Leafrunner - Actionlist - Remove Timed Event 61');
+331
View File
@@ -0,0 +1,331 @@
-- DB update 2023_06_26_00 -> 2023_06_26_01
--
SET @OGUID := 76200;
DELETE FROM `gameobject` WHERE `id` = 181288 AND `guid` BETWEEN @OGUID AND @OGUID+77;
INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`) VALUES
(@OGUID+0 , 181288, 0, 0, 0, 1, 1, -14376.7, 115.921, 1.4532, 2.11185, 0, 0, 0.870356, 0.492423, 180, 100, 1, '', 0),
(@OGUID+1 , 181288, 0, 0, 0, 1, 1, -14288.1, 61.8062, 0.68836, 1.37881, 0, 0, 0.636078, 0.771625, 180, 100, 1, '', 0),
(@OGUID+2 , 181288, 0, 0, 0, 1, 1, -10951.5, -3218.1, 41.3475, 1.91986, 0, 0, 0.819151, 0.573577, 180, 100, 1, '', 0),
(@OGUID+3 , 181288, 0, 0, 0, 1, 1, -10704.8, -1146.38, 24.7909, 2.09439, 0, 0, 0.866024, 0.500002, 180, 100, 1, '', 0),
(@OGUID+4 , 181288, 0, 0, 0, 1, 1, -10657.1, 1054.63, 32.6733, 2.47837, 0, 0, 0.945519, 0.325567, 180, 100, 1, '', 0),
(@OGUID+5 , 181288, 0, 0, 0, 1, 1, -10331.4, -3297.73, 21.9992, -2.89725, 0, 0, -0.992546, 0.121868, 180, 100, 1, '', 0),
(@OGUID+6 , 181288, 0, 0, 0, 1, 1, -9434.3, -2110.36, 65.8038, 0.349066, 0, 0, 0.173648, 0.984808, 180, 100, 1, '', 0),
(@OGUID+7 , 181288, 0, 0, 0, 1, 1, -9394.21, 37.5017, 59.882, 1.15192, 0, 0, 0.54464, 0.83867, 180, 100, 1, '', 0),
(@OGUID+8 , 181288, 0, 0, 0, 1, 1, -8245.62, -2623.9, 133.155, 4.04776, 0, 0, 0.899102, -0.43774, 300, 0, 1, '', 0),
(@OGUID+9 , 181288, 0, 0, 0, 1, 1, -7596.42, -2086.6, 125.17, -0.942478, 0, 0, -0.453991, 0.891006, 180, 100, 1, '', 0),
(@OGUID+10, 181288, 0, 0, 0, 1, 1, -6704.48, -2200.91, 248.609, 0.017453, 0, 0, 0.00872639, 0.999962, 180, 100, 1, '', 0),
(@OGUID+11, 181288, 0, 0, 0, 1, 1, -5404.93, -492.299, 395.597, -0.506145, 0, 0, -0.25038, 0.968148, 180, 100, 1, '', 0),
(@OGUID+12, 181288, 0, 0, 0, 1, 1, -5233.16, -2893.37, 337.286, -0.226893, 0, 0, -0.113203, 0.993572, 180, 100, 1, '', 0),
(@OGUID+13, 181288, 0, 0, 0, 1, 1, -3448.2, -938.102, 10.6583, 0.034907, 0, 0, 0.0174526, 0.999848, 180, 100, 1, '', 0),
(@OGUID+14, 181288, 0, 0, 0, 1, 1, -1211.6, -2676.88, 45.3612, -0.645772, 0, 0, -0.317305, 0.948324, 180, 100, 1, '', 0),
(@OGUID+15, 181288, 0, 0, 0, 1, 1, -1134.84, -3531.81, 51.0719, -0.820305, 0, 0, -0.398749, 0.91706, 180, 100, 1, '', 0),
(@OGUID+16, 181288, 0, 0, 0, 1, 1, -604.148, -545.813, 36.579, 0.698132, 0, 0, 0.34202, 0.939693, 180, 100, 1, '', 0),
(@OGUID+17, 181288, 0, 0, 0, 1, 1, -447.95, -4527.65, 8.59595, 1.53589, 0, 0, 0.694658, 0.71934, 180, 100, 1, '', 0),
(@OGUID+18, 181288, 0, 0, 0, 1, 1, -134.688, -802.767, 55.0147, -1.62316, 0, 0, -0.725376, 0.688353, 180, 100, 1, '', 0),
(@OGUID+19, 181288, 0, 0, 0, 1, 1, 188.243, -2132.53, 102.674, -1.37881, 0, 0, -0.636078, 0.771625, 180, 100, 1, '', 0),
(@OGUID+20, 181288, 0, 0, 0, 1, 1, 587.056, 1365.02, 90.4778, 2.6529, 0, 0, 0.970296, 0.241922, 180, 100, 1, '', 0),
(@OGUID+21, 181288, 0, 0, 0, 1, 1, 989.562, -1453.47, 61.0011, 4.9105, 0, 0, 0.633712, -0.773569, 300, 0, 1, '', 0),
(@OGUID+22, 181288, 0, 0, 0, 1, 1, 2279.25, 456.009, 33.867, 0.3665, 0, 0, 0.182226, 0.983257, 120, 0, 1, '', 0),
(@OGUID+23, 181288, 1, 0, 0, 1, 1, -7216.68, -3859.39, 11.4943, -2.72271, 0, 0, -0.978147, 0.207914, 300, 0, 1, '', 0),
(@OGUID+24, 181288, 1, 0, 0, 1, 1, -7122.51, -3657.11, 8.82202, -1.74533, 0, 0, -0.766045, 0.642787, 180, 100, 1, '', 0),
(@OGUID+25, 181288, 1, 0, 0, 1, 1, -7000.75, 918.851, 8.93831, -2.23402, 0, 0, -0.898794, 0.438372, 900, 100, 1, '', 0),
(@OGUID+26, 181288, 1, 0, 0, 1, 1, -6771.96, 527.151, -1.40004, 3.1949, 0, 0, 0.999645, -0.0266505, 300, 0, 1, '', 0),
(@OGUID+27, 181288, 1, 0, 0, 1, 1, -5513.93, -2299.73, -58.0752, 2.44346, 0, 0, 0.939692, 0.342021, 180, 100, 1, '', 0),
(@OGUID+28, 181288, 1, 0, 0, 1, 1, -4573.22, 407.388, 41.5461, 2.46091, 0, 0, 0.942641, 0.333809, 180, 100, 1, '', 0),
(@OGUID+29, 181288, 1, 0, 0, 1, 1, -4412.02, 3480.24, 12.6312, 6.12709, 0, 0, 0.0779684, -0.996956, 300, 0, 1, '', 0),
(@OGUID+30, 181288, 1, 0, 0, 1, 1, -3447.55, -4231.67, 10.6645, 0.802851, 0, 0, 0.390731, 0.920505, 180, 100, 1, '', 0),
(@OGUID+31, 181288, 1, 0, 0, 1, 1, -3110.59, -2722.41, 33.4626, 0.226893, 0, 0, 0.113203, 0.993572, 180, 100, 1, '', 0),
(@OGUID+32, 181288, 1, 0, 0, 1, 1, -2329.42, -624.806, -8.27507, 5.5, 0, 0, 0.381661, -0.924302, 0, 100, 1, '', 0),
(@OGUID+33, 181288, 1, 0, 0, 1, 1, -1862.36, 3055.71, 0.744157, 2.49582, 0, 0, 0.948324, 0.317305, 180, 100, 1, '', 0),
(@OGUID+34, 181288, 1, 0, 0, 1, 1, -273.242, -2662.82, 91.695, -1.8675, 0, 0, -0.803856, 0.594824, 180, 100, 1, '', 0),
(@OGUID+35, 181288, 1, 0, 0, 1, 1, -55.5039, 1271.35, 91.9489, 1.5708, 0, 0, 0.707108, 0.707106, 180, 100, 1, '', 0),
(@OGUID+36, 181288, 1, 0, 0, 1, 1, 145.521, -4713.82, 18.129, -2.53, 0, 0, -0.953607, 0.301053, 120, 0, 1, '', 0),
(@OGUID+37, 181288, 1, 0, 0, 1, 1, 952.992, 776.968, 104.474, -1.55334, 0, 0, -0.700908, 0.713252, 180, 100, 1, '', 0),
(@OGUID+38, 181288, 1, 0, 0, 1, 1, 2014.65, -2337.84, 89.5211, 2.37365, 0, 0, 0.927184, 0.374606, 180, 100, 1, '', 0),
(@OGUID+39, 181288, 1, 0, 0, 1, 1, 2558.73, -481.666, 109.821, -2.47837, 0, 0, -0.945519, 0.325567, 180, 100, 1, '', 0),
(@OGUID+40, 181288, 1, 0, 0, 1, 1, 6327.68, 512.61, 17.4723, 0.034907, 0, 0, 0.0174526, 0.999848, 180, 100, 1, '', 0),
(@OGUID+41, 181288, 1, 0, 0, 1, 1, 6855.99, -4564.4, 708.51, 0.855211, 0, 0, 0.414693, 0.909961, 180, 100, 1, '', 0),
(@OGUID+42, 181288, 1, 0, 0, 1, 1, 6860.03, -4767.11, 696.833, -2.63545, 0, 0, -0.968148, 0.250379, 180, 100, 1, '', 0),
(@OGUID+43, 181288, 1, 0, 0, 1, 1, 9778.64, 1019.38, 1299.79, 0.261799, 0, 0, 0.130526, 0.991445, 180, 100, 1, '', 0),
(@OGUID+44, 181288, 530, 0, 0, 1, 1, -4223.84, -12318.4, 2.47695, 5.69342, 0, 0, 0.290628, -0.956836, 300, 0, 1, '', 0),
(@OGUID+45, 181288, 530, 0, 0, 1, 1, -3941.98, 2048.49, 95.0656, 4.87742, 0, 0, 0.64642, -0.762982, 300, 0, 1, '', 0),
(@OGUID+46, 181288, 530, 0, 0, 1, 1, -3059.17, 2374.85, 63.1011, 2.03334, 0, 0, 0.850361, 0.526201, 300, 0, 1, '', 0),
(@OGUID+47, 181288, 530, 0, 0, 1, 1, -3004.07, 4152.48, 3.64988, 1.75455, 0, 0, 0.769, 0.639249, 300, 0, 1, '', 0),
(@OGUID+48, 181288, 530, 0, 0, 1, 1, -2553.32, 4277.61, 20.614, -1.36136, 0, 0, -0.629322, 0.777145, 180, 100, 1, '', 0),
(@OGUID+49, 181288, 530, 0, 0, 1, 1, -2526.69, 7548.83, -2.23534, 5.32817, 0, 0, 0.459567, -0.888143, 300, 0, 1, '', 0),
(@OGUID+50, 181288, 530, 0, 0, 1, 1, -2254.78, -11896.3, 27.4979, 5.24028, 0, 0, 0.49814, -0.867096, 300, 0, 1, '', 0),
(@OGUID+51, 181288, 530, 0, 0, 1, 1, -1211.01, 7474.44, 21.9953, -2.02458, 0, 0, -0.848048, 0.52992, 180, 100, 1, '', 0),
(@OGUID+52, 181288, 530, 0, 0, 1, 1, -528.509, 2339.11, 38.7252, 2.14675, 0, 0, 0.878816, 0.477161, 180, 100, 1, '', 0),
(@OGUID+53, 181288, 530, 0, 0, 1, 1, 41.2448, 2587.44, 68.3453, -2.28638, 0, 0, -0.909961, 0.414694, 180, 100, 1, '', 0),
(@OGUID+54, 181288, 530, 0, 0, 1, 1, 192.209, 6015.13, 22.1067, 0.00709009, 0, 0, 0.00354504, 0.999994, 300, 0, 1, '', 0),
(@OGUID+55, 181288, 530, 0, 0, 1, 1, 200.9, 7686.96, 22.508, -0.506145, 0, 0, -0.25038, 0.968148, 180, 100, 1, '', 0),
(@OGUID+56, 181288, 530, 0, 0, 1, 1, 2019.7, 6587.14, 134.985, 6.23705, 0, 0, 0.0230656, -0.999734, 300, 0, 1, '', 0),
(@OGUID+57, 181288, 530, 0, 0, 1, 1, 2282.43, 6134.5, 136.337, 6.01364, 0, 0, 0.134365, -0.990932, 300, 0, 1, '', 0),
(@OGUID+58, 181288, 530, 0, 0, 1, 1, 2922.17, 3690.15, 143.809, 5.94709, 0, 0, 0.167258, -0.985913, 300, 0, 1, '', 0),
(@OGUID+59, 181288, 530, 0, 0, 1, 1, 3121.5, 3753.88, 141.851, 5.85856, 0, 0, 0.210721, -0.977546, 300, 0, 1, '', 0),
(@OGUID+60, 181288, 530, 0, 0, 1, 1, 7693.53, -6836.51, 77.787, 2.7052, 0, 0, 0.976289, 0.216469, 120, 0, 1, '', 0),
(@OGUID+61, 181288, 530, 0, 0, 1, 1, 9386.86, -6772.24, 14.412, -2.9146, 0, 0, -0.993566, 0.113253, 120, 0, 1, '', 0),
(@OGUID+62, 181288, 571, 0, 0, 1, 1, 2454.19, -4910.31, 263.893, 1.66082, 0, 0, 0.738208, 0.674573, 300, 0, 1, '', 0),
(@OGUID+63, 181288, 571, 0, 0, 1, 1, 2579.72, -4325.59, 276.934, 5.77529, 0, 0, 0.251227, -0.967928, 300, 0, 1, '', 0),
(@OGUID+64, 181288, 571, 0, 0, 1, 1, 3368.48, -2135.25, 124.53, 0.20224, 0, 0, 0.100948, 0.994892, 300, 0, 1, '', 0),
(@OGUID+65, 181288, 571, 0, 0, 1, 1, 3403.4, -2896.41, 201.988, 2.32303, 0, 0, 0.917407, 0.39795, 300, 0, 1, '', 0),
(@OGUID+66, 181288, 571, 0, 0, 1, 1, 3773.85, 1464.02, 92.4174, 6.10863, 0, 0, 0.0871668, -0.996194, 300, 0, 1, '', 0),
(@OGUID+67, 181288, 571, 0, 0, 1, 1, 3936.15, -583.456, 240.5, 4.0611, 0, 0, 0.896162, -0.443727, 300, 0, 1, '', 0),
(@OGUID+68, 181288, 571, 0, 0, 1, 1, 4122.37, 5390.27, 27.8408, 5.32484, 0, 0, 0.461045, -0.887377, 300, 0, 1, '', 0),
(@OGUID+69, 181288, 571, 0, 0, 1, 1, 4441.05, 5627.71, 56.3487, 4.54665, 0, 0, 0.763211, -0.64615, 300, 0, 1, '', 0),
(@OGUID+70, 181288, 571, 0, 0, 1, 1, 5144.94, -695.736, 171.284, 5.22017, 0, 0, 0.506834, -0.862044, 300, 0, 1, '', 0),
(@OGUID+71, 181288, 571, 0, 0, 1, 1, 5294.92, -2761.88, 292.419, 2.12359, 0, 0, 0.873232, 0.487305, 300, 0, 1, '', 0),
(@OGUID+72, 181288, 571, 0, 0, 1, 1, 5369.18, 4842.41, -197.357, 4.53948, 0, 0, 0.765522, -0.643409, 300, 0, 1, '', 0),
(@OGUID+73, 181288, 571, 0, 0, 1, 1, 5499.12, 4869.82, -197.467, 5.88414, 0, 0, 0.198201, -0.980161, 300, 0, 1, '', 0),
(@OGUID+74, 181288, 571, 0, 0, 1, 1, 5530.53, -726.151, 148.904, 5.3977, 0, 0, 0.428419, -0.90358, 300, 0, 1, '', 0),
(@OGUID+75, 181288, 571, 0, 0, 1, 1, 5626.92, -2622.29, 292.417, 1.6785, 0, 0, 0.744142, 0.668021, 300, 0, 1, '', 0),
(@OGUID+76, 181288, 571, 0, 0, 1, 1, 6081.58, -1107.81, 419.498, 5.2117, 0, 0, 0.51048, -0.85989, 300, 0, 1, '', 0),
(@OGUID+77, 181288, 571, 0, 0, 1, 1, 6142.19, -1020.44, 408.496, 1.91604, 0, 0, 0.818054, 0.575141, 300, 0, 1, '', 0);
DELETE FROM `game_event_gameobject` WHERE `eventEntry` = 1 AND `guid` BETWEEN @OGUID AND @OGUID+77;
INSERT INTO `game_event_gameobject` (`eventEntry`, `guid`) VALUES
(1, @OGUID+0 ),
(1, @OGUID+1 ),
(1, @OGUID+2 ),
(1, @OGUID+3 ),
(1, @OGUID+4 ),
(1, @OGUID+5 ),
(1, @OGUID+6 ),
(1, @OGUID+7 ),
(1, @OGUID+8 ),
(1, @OGUID+9 ),
(1, @OGUID+10),
(1, @OGUID+11),
(1, @OGUID+12),
(1, @OGUID+13),
(1, @OGUID+14),
(1, @OGUID+15),
(1, @OGUID+16),
(1, @OGUID+17),
(1, @OGUID+18),
(1, @OGUID+19),
(1, @OGUID+20),
(1, @OGUID+21),
(1, @OGUID+22),
(1, @OGUID+23),
(1, @OGUID+24),
(1, @OGUID+25),
(1, @OGUID+26),
(1, @OGUID+27),
(1, @OGUID+28),
(1, @OGUID+29),
(1, @OGUID+30),
(1, @OGUID+31),
(1, @OGUID+32),
(1, @OGUID+33),
(1, @OGUID+34),
(1, @OGUID+35),
(1, @OGUID+36),
(1, @OGUID+37),
(1, @OGUID+38),
(1, @OGUID+39),
(1, @OGUID+40),
(1, @OGUID+41),
(1, @OGUID+42),
(1, @OGUID+43),
(1, @OGUID+44),
(1, @OGUID+45),
(1, @OGUID+46),
(1, @OGUID+47),
(1, @OGUID+48),
(1, @OGUID+49),
(1, @OGUID+50),
(1, @OGUID+51),
(1, @OGUID+52),
(1, @OGUID+53),
(1, @OGUID+54),
(1, @OGUID+55),
(1, @OGUID+56),
(1, @OGUID+57),
(1, @OGUID+58),
(1, @OGUID+59),
(1, @OGUID+60),
(1, @OGUID+61),
(1, @OGUID+62),
(1, @OGUID+63),
(1, @OGUID+64),
(1, @OGUID+65),
(1, @OGUID+66),
(1, @OGUID+67),
(1, @OGUID+68),
(1, @OGUID+69),
(1, @OGUID+70),
(1, @OGUID+71),
(1, @OGUID+72),
(1, @OGUID+73),
(1, @OGUID+74),
(1, @OGUID+75),
(1, @OGUID+76),
(1, @OGUID+77);
SET @OGUID := 76300;
DELETE FROM `gameobject` WHERE `id` IN (SELECT `entry` FROM `gameobject_template` WHERE `name` IN ('Horde Bonfire', 'Alliance Bonfire')) /* AND `guid` BETWEEN @OGUID AND @OGUID+77 */;
INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `ScriptName`, `VerifiedBuild`) VALUES
(@OGUID+0 , 187951, 0, 0, 0, 1, 1, -14376.7, 115.921, 1.4532, 2.11185, 0, 0, 0.870356, 0.492423, 180, 100, 1, '', 0),
(@OGUID+1 , 187944, 0, 0, 0, 1, 1, -14288.1, 61.8062, 0.68836, 1.37881, 0, 0, 0.636078, 0.771625, 180, 100, 1, '', 0),
(@OGUID+2 , 187920, 0, 0, 0, 1, 1, -10951.5, -3218.1, 41.3475, 1.91986, 0, 0, 0.819151, 0.573577, 180, 100, 1, '', 0),
(@OGUID+3 , 187926, 0, 0, 0, 1, 1, -10704.8, -1146.38, 24.7909, 2.09439, 0, 0, 0.866024, 0.500002, 180, 100, 1, '', 0),
(@OGUID+4 , 187564, 0, 0, 0, 1, 1, -10657.1, 1054.63, 32.6733, 2.47837, 0, 0, 0.945519, 0.325567, 180, 100, 1, '', 0),
(@OGUID+5 , 187969, 0, 0, 0, 1, 1, -10331.4, -3297.73, 21.9992, -2.89725, 0, 0, -0.992546, 0.121868, 180, 100, 1, '', 0),
(@OGUID+6 , 187934, 0, 0, 0, 1, 1, -9434.3, -2110.36, 65.8038, 0.349066, 0, 0, 0.173648, 0.984808, 180, 100, 1, '', 0),
(@OGUID+7 , 187928, 0, 0, 0, 1, 1, -9394.21, 37.5017, 59.882, 1.15192, 0, 0, 0.54464, 0.83867, 180, 100, 1, '', 0),
(@OGUID+8 , 187922, 0, 0, 0, 1, 1, -8245.62, -2623.9, 133.155, 4.04776, 0, 0, 0.899102, -0.43774, 300, 0, 1, '', 0),
(@OGUID+9 , 187956, 0, 0, 0, 1, 1, -7596.42, -2086.6, 125.17, -0.942478, 0, 0, -0.453991, 0.891006, 180, 100, 1, '', 0),
(@OGUID+10, 187954, 0, 0, 0, 1, 1, -6704.48, -2200.91, 248.609, 0.017453, 0, 0, 0.00872639, 0.999962, 180, 100, 1, '', 0),
(@OGUID+11, 187925, 0, 0, 0, 1, 1, -5404.93, -492.299, 395.597, -0.506145, 0, 0, -0.25038, 0.968148, 180, 100, 1, '', 0),
(@OGUID+12, 187932, 0, 0, 0, 1, 1, -5233.16, -2893.37, 337.286, -0.226893, 0, 0, -0.113203, 0.993572, 180, 100, 1, '', 0),
(@OGUID+13, 187940, 0, 0, 0, 1, 1, -3448.2, -938.102, 10.6583, 0.034907, 0, 0, 0.0174526, 0.999848, 180, 100, 1, '', 0),
(@OGUID+14, 187914, 0, 0, 0, 1, 1, -1211.6, -2676.88, 45.3612, -0.645772, 0, 0, -0.317305, 0.948324, 180, 100, 1, '', 0),
(@OGUID+15, 187947, 0, 0, 0, 1, 1, -1134.84, -3531.81, 51.0719, -0.820305, 0, 0, -0.398749, 0.91706, 180, 100, 1, '', 0),
(@OGUID+16, 187931, 0, 0, 0, 1, 1, -604.148, -545.813, 36.579, 0.698132, 0, 0, 0.34202, 0.939693, 180, 100, 1, '', 0),
(@OGUID+17, 187972, 0, 0, 0, 1, 1, -447.95, -4527.65, 8.59595, 1.53589, 0, 0, 0.694658, 0.71934, 180, 100, 1, '', 0),
(@OGUID+18, 187964, 0, 0, 0, 1, 1, -134.688, -802.767, 55.0147, -1.62316, 0, 0, -0.725376, 0.688353, 180, 100, 1, '', 0),
(@OGUID+19, 187938, 0, 0, 0, 1, 1, 188.243, -2132.53, 102.674, -1.37881, 0, 0, -0.636078, 0.771625, 180, 100, 1, '', 0),
(@OGUID+20, 187559, 0, 0, 0, 1, 1, 587.056, 1365.02, 90.4778, 2.6529, 0, 0, 0.970296, 0.241922, 180, 100, 1, '', 0),
(@OGUID+21, 187939, 0, 0, 0, 1, 1, 989.562, -1453.47, 61.0011, 4.9105, 0, 0, 0.633712, -0.773569, 120, 255, 1, '', 0),
(@OGUID+22, 187974, 0, 0, 0, 1, 1, 2279.25, 456.009, 33.867, 0.3665, 0, 0, 0.182226, 0.983257, 120, 0, 1, '', 0),
(@OGUID+23, 187945, 1, 0, 0, 1, 1, -7216.68, -3859.39, 11.4943, -2.72271, 0, 0, -0.978147, 0.207914, 180, 100, 1, '', 0),
(@OGUID+24, 187952, 1, 0, 0, 1, 1, -7122.51, -3657.11, 8.82202, -1.74533, 0, 0, -0.766045, 0.642787, 180, 100, 1, '', 0),
(@OGUID+25, 187950, 1, 0, 0, 1, 1, -7000.75, 918.851, 8.93831, -2.23402, 0, 0, -0.898794, 0.438372, 180, 100, 1, '', 0),
(@OGUID+26, 187943, 1, 0, 0, 1, 1, -6771.96, 527.151, -1.40004, 3.1949, 0, 0, 0.999645, -0.0266505, 300, 0, 1, '', 0),
(@OGUID+27, 187973, 1, 0, 0, 1, 1, -5513.93, -2299.73, -58.0752, 2.44346, 0, 0, 0.939692, 0.342021, 180, 100, 1, '', 0),
(@OGUID+28, 187961, 1, 0, 0, 1, 1, -4573.22, 407.388, 41.5461, 2.46091, 0, 0, 0.942641, 0.333809, 180, 100, 1, '', 0),
(@OGUID+29, 187929, 1, 0, 0, 1, 1, -4412.02, 3480.24, 12.6312, 6.12709, 0, 0, 0.0779684, -0.996956, 300, 0, 1, '', 0),
(@OGUID+30, 187927, 1, 0, 0, 1, 1, -3447.55, -4231.67, 10.6645, 0.802851, 0, 0, 0.390731, 0.920505, 180, 100, 1, '', 0),
(@OGUID+31, 187959, 1, 0, 0, 1, 1, -3110.59, -2722.41, 33.4626, 0.226893, 0, 0, 0.113203, 0.993572, 180, 100, 1, '', 0),
(@OGUID+32, 187965, 1, 0, 0, 1, 1, -2329.42, -624.806, -8.27507, 5.5, 0, 0, 0.381661, -0.924302, 0, 100, 1, '', 0),
(@OGUID+33, 187957, 1, 0, 0, 1, 1, -1862.36, 3055.71, 0.744157, 2.49582, 0, 0, 0.948324, 0.317305, 180, 100, 1, '', 0),
(@OGUID+34, 187971, 1, 0, 0, 1, 1, -273.242, -2662.82, 91.695, -1.8675, 0, 0, -0.803856, 0.594824, 180, 100, 1, '', 0),
(@OGUID+35, 187924, 1, 0, 0, 1, 1, -55.5039, 1271.35, 91.9489, 1.5708, 0, 0, 0.707108, 0.707106, 180, 100, 1, '', 0),
(@OGUID+36, 187958, 1, 0, 0, 1, 1, 145.521, -4713.82, 18.129, -2.53, 0, 0, -0.953607, 0.301053, 120, 0, 1, '', 0),
(@OGUID+37, 187968, 1, 0, 0, 1, 1, 952.992, 776.968, 104.474, -1.55334, 0, 0, -0.700908, 0.713252, 180, 100, 1, '', 0),
(@OGUID+38, 187948, 1, 0, 0, 1, 1, 2014.65, -2337.84, 89.5211, 2.37365, 0, 0, 0.927184, 0.374606, 180, 100, 1, '', 0),
(@OGUID+39, 187916, 1, 0, 0, 1, 1, 2558.73, -481.666, 109.821, -2.47837, 0, 0, -0.945519, 0.325567, 180, 100, 1, '', 0),
(@OGUID+40, 187923, 1, 0, 0, 1, 1, 6327.68, 512.61, 17.4723, 0.034907, 0, 0, 0.0174526, 0.999848, 180, 100, 1, '', 0),
(@OGUID+41, 187953, 1, 0, 0, 1, 1, 6855.99, -4564.4, 708.51, 0.855211, 0, 0, 0.414693, 0.909961, 180, 100, 1, '', 0),
(@OGUID+42, 187946, 1, 0, 0, 1, 1, 6860.03, -4767.11, 696.833, -2.63545, 0, 0, -0.968148, 0.250379, 180, 100, 1, '', 0),
(@OGUID+43, 187936, 1, 0, 0, 1, 1, 9778.64, 1019.38, 1299.79, 0.261799, 0, 0, 0.130526, 0.991445, 180, 100, 1, '', 0),
(@OGUID+44, 187917, 530, 0, 0, 1, 1, -4223.84, -12318.4, 2.47695, 2.93214, 0, 0, 0.994521, 0.104535, 120, 255, 1, '', 0),
(@OGUID+45, 187935, 530, 0, 0, 1, 1, -3941.98, 2048.49, 95.0656, 4.87742, 0, 0, 0.64642, -0.762982, 300, 0, 1, '', 0),
(@OGUID+46, 187967, 530, 0, 0, 1, 1, -3059.17, 2374.85, 63.1011, 2.03334, 0, 0, 0.850361, 0.526201, 300, 0, 1, '', 0),
(@OGUID+47, 187937, 530, 0, 0, 1, 1, -3004.07, 4152.48, 3.64988, 1.75455, 0, 0, 0.769, 0.639249, 300, 0, 1, '', 0),
(@OGUID+48, 187970, 530, 0, 0, 1, 1, -2553.32, 4277.61, 20.614, -1.36136, 0, 0, -0.629322, 0.777145, 180, 100, 1, '', 0),
(@OGUID+49, 187933, 530, 0, 0, 1, 1, -2526.69, 7548.83, -2.23534, 5.32817, 0, 0, 0.459567, -0.888143, 300, 0, 1, '', 0),
(@OGUID+50, 187921, 530, 0, 0, 1, 1, -2254.78, -11896.3, 27.4979, 5.24028, 0, 0, 0.49814, -0.867096, 300, 0, 1, '', 0),
(@OGUID+51, 187966, 530, 0, 0, 1, 1, -1211.01, 7474.44, 21.9953, -2.02458, 0, 0, -0.848048, 0.52992, 180, 100, 1, '', 0),
(@OGUID+52, 187930, 530, 0, 0, 1, 1, -528.509, 2339.11, 38.7252, 2.14675, 0, 0, 0.878816, 0.477161, 180, 100, 1, '', 0),
(@OGUID+53, 187963, 530, 0, 0, 1, 1, 41.2448, 2587.44, 68.3453, -2.28638, 0, 0, -0.909961, 0.414694, 180, 100, 1, '', 0),
(@OGUID+54, 187941, 530, 0, 0, 1, 1, 192.209, 6015.13, 22.1067, 0.00709009, 0, 0, 0.00354504, 0.999994, 300, 0, 1, '', 0),
(@OGUID+55, 187975, 530, 0, 0, 1, 1, 200.9, 7686.96, 22.508, -0.506145, 0, 0, -0.25038, 0.968148, 180, 100, 1, '', 0),
(@OGUID+56, 187919, 530, 0, 0, 1, 1, 2019.7, 6587.14, 134.985, 6.23705, 0, 0, 0.0230656, -0.999734, 120, 255, 1, '', 0),
(@OGUID+57, 187955, 530, 0, 0, 1, 1, 2282.43, 6134.5, 136.337, 6.01364, 0, 0, 0.134365, -0.990932, 300, 0, 1, '', 0),
(@OGUID+58, 187949, 530, 0, 0, 1, 1, 2922.17, 3690.15, 143.809, 5.94709, 0, 0, 0.167258, -0.985913, 300, 0, 1, '', 0),
(@OGUID+59, 187942, 530, 0, 0, 1, 1, 3121.5, 3753.88, 141.851, 5.85856, 0, 0, 0.210721, -0.977546, 300, 0, 1, '', 0),
(@OGUID+60, 187962, 530, 0, 0, 1, 1, 7693.53, -6836.51, 77.787, 2.7052, 0, 0, 0.976289, 0.216469, 120, 0, 1, '', 0),
(@OGUID+61, 187960, 530, 0, 0, 1, 1, 9386.86, -6772.24, 14.412, -2.9146, 0, 0, -0.993566, 0.113253, 120, 0, 1, '', 0),
(@OGUID+62, 194038, 571, 0, 0, 1, 1, 2454.19, -4910.31, 263.893, 1.66082, 0, 0, 0.738208, 0.674573, 300, 0, 1, '', 0),
(@OGUID+63, 194039, 571, 0, 0, 1, 1, 2579.72, -4325.59, 276.934, 5.77529, 0, 0, 0.251227, -0.967928, 300, 0, 1, '', 0),
(@OGUID+64, 194042, 571, 0, 0, 1, 1, 3368.48, -2135.25, 124.53, 0.20224, 0, 0, 0.100948, 0.994892, 300, 0, 1, '', 0),
(@OGUID+65, 194040, 571, 0, 0, 1, 1, 3403.4, -2896.41, 201.988, 2.32303, 0, 0, 0.917407, 0.39795, 300, 0, 1, '', 0),
(@OGUID+66, 194037, 571, 0, 0, 1, 1, 3773.85, 1464.02, 92.4174, 6.10863, 0, 0, 0.0871668, -0.996194, 300, 0, 1, '', 0),
(@OGUID+67, 194036, 571, 0, 0, 1, 1, 3936.15, -583.456, 240.5, 4.0611, 0, 0, 0.896162, -0.443727, 300, 0, 1, '', 0),
(@OGUID+68, 194032, 571, 0, 0, 1, 1, 4122.37, 5390.27, 27.8408, 5.32484, 0, 0, 0.461045, -0.887377, 300, 0, 1, '', 0),
(@OGUID+69, 194033, 571, 0, 0, 1, 1, 4441.05, 5627.71, 56.3487, 4.54665, 0, 0, 0.763211, -0.64615, 300, 0, 1, '', 0),
(@OGUID+70, 194045, 571, 0, 0, 1, 1, 5144.94, -695.736, 171.284, 5.22017, 0, 0, 0.506834, -0.862044, 300, 0, 1, '', 0),
(@OGUID+71, 194048, 571, 0, 0, 1, 1, 5294.92, -2761.88, 292.419, 2.12359, 0, 0, 0.873232, 0.487305, 300, 0, 1, '', 0),
(@OGUID+72, 194035, 571, 0, 0, 1, 1, 5369.18, 4842.41, -197.357, 4.53948, 0, 0, 0.765522, -0.643409, 300, 0, 1, '', 0),
(@OGUID+73, 194034, 571, 0, 0, 1, 1, 5499.12, 4869.82, -197.467, 5.88414, 0, 0, 0.198201, -0.980161, 300, 0, 1, '', 0),
(@OGUID+74, 194046, 571, 0, 0, 1, 1, 5530.53, -726.151, 148.904, 5.3977, 0, 0, 0.428419, -0.90358, 300, 0, 1, '', 0),
(@OGUID+75, 194049, 571, 0, 0, 1, 1, 5626.92, -2622.29, 292.417, 1.6785, 0, 0, 0.744142, 0.668021, 300, 0, 1, '', 0),
(@OGUID+76, 194044, 571, 0, 0, 1, 1, 6081.58, -1107.81, 419.498, 5.2117, 0, 0, 0.51048, -0.85989, 300, 0, 1, '', 0),
(@OGUID+77, 194043, 571, 0, 0, 1, 1, 6142.19, -1020.44, 408.496, 1.91604, 0, 0, 0.818054, 0.575141, 300, 0, 1, '', 0);
DELETE FROM `game_event_gameobject` WHERE `eventEntry` = 1 AND `guid` BETWEEN @OGUID AND @OGUID+77;
INSERT INTO `game_event_gameobject` (`eventEntry`, `guid`) VALUES
(1, @OGUID+0 ),
(1, @OGUID+1 ),
(1, @OGUID+2 ),
(1, @OGUID+3 ),
(1, @OGUID+4 ),
(1, @OGUID+5 ),
(1, @OGUID+6 ),
(1, @OGUID+7 ),
(1, @OGUID+8 ),
(1, @OGUID+9 ),
(1, @OGUID+10),
(1, @OGUID+11),
(1, @OGUID+12),
(1, @OGUID+13),
(1, @OGUID+14),
(1, @OGUID+15),
(1, @OGUID+16),
(1, @OGUID+17),
(1, @OGUID+18),
(1, @OGUID+19),
(1, @OGUID+20),
(1, @OGUID+21),
(1, @OGUID+22),
(1, @OGUID+23),
(1, @OGUID+24),
(1, @OGUID+25),
(1, @OGUID+26),
(1, @OGUID+27),
(1, @OGUID+28),
(1, @OGUID+29),
(1, @OGUID+30),
(1, @OGUID+31),
(1, @OGUID+32),
(1, @OGUID+33),
(1, @OGUID+34),
(1, @OGUID+35),
(1, @OGUID+36),
(1, @OGUID+37),
(1, @OGUID+38),
(1, @OGUID+39),
(1, @OGUID+40),
(1, @OGUID+41),
(1, @OGUID+42),
(1, @OGUID+43),
(1, @OGUID+44),
(1, @OGUID+45),
(1, @OGUID+46),
(1, @OGUID+47),
(1, @OGUID+48),
(1, @OGUID+49),
(1, @OGUID+50),
(1, @OGUID+51),
(1, @OGUID+52),
(1, @OGUID+53),
(1, @OGUID+54),
(1, @OGUID+55),
(1, @OGUID+56),
(1, @OGUID+57),
(1, @OGUID+58),
(1, @OGUID+59),
(1, @OGUID+60),
(1, @OGUID+61),
(1, @OGUID+62),
(1, @OGUID+63),
(1, @OGUID+64),
(1, @OGUID+65),
(1, @OGUID+66),
(1, @OGUID+67),
(1, @OGUID+68),
(1, @OGUID+69),
(1, @OGUID+70),
(1, @OGUID+71),
(1, @OGUID+72),
(1, @OGUID+73),
(1, @OGUID+74),
(1, @OGUID+75),
(1, @OGUID+76),
(1, @OGUID+77);
DELETE FROM `game_event_gameobject` WHERE `eventEntry` = 1 AND `guid` BETWEEN 242500 AND 242577;
@@ -0,0 +1,4 @@
-- DB update 2023_06_26_01 -> 2023_06_27_00
-- 31994 - Shoulder Charge
DELETE FROM `spell_custom_attr` WHERE `spell_id` = 31994;
INSERT INTO `spell_custom_attr` (`spell_id`, `attributes`) VALUES (31994, 16384);
@@ -0,0 +1,4 @@
-- DB update 2023_06_27_00 -> 2023_06_29_00
DELETE FROM `quest_offer_reward_locale` WHERE `ID`=1045 AND `locale`='ruRU';
INSERT INTO `quest_offer_reward_locale` (`ID`, `locale`, `RewardText`, `VerifiedBuild`) VALUES
(1045, 'ruRU', 'Славная работа, $N. Спасибо тебе.', 18019);
@@ -0,0 +1,4 @@
-- DB update 2023_06_29_00 -> 2023_06_29_01
--
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|128 WHERE `entry`=22021;
@@ -0,0 +1,23 @@
-- DB update 2023_06_29_01 -> 2023_06_29_02
-- Fix SAI Yenniku --
DELETE FROM `creature_text` WHERE (`CreatureID` = 2530 AND `GroupID` = 0);
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
(2530, 0, 0, '%s is struck dumb by the Soul Gem!', 16, 0, 100, 0, 0, 0, 681, 0, 'Yenniku');
UPDATE `creature_template` SET `AIName` = 'SmartAI', `ScriptName` = '' WHERE (`entry` = 2530);
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 2530);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(2530, 0, 0, 1, 8, 0, 100, 0, 3607, 0, 30000, 30000, 0, 2, 35, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - On Spellhit \'Yenniku`s Release\' - Set Faction 35'),
(2530, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 80, 253000, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - On Spellhit \'Yenniku`s Release\' - Run Script'),
(2530, 0, 2, 0, 20, 0, 100, 0, 593, 0, 0, 0, 0, 80, 253001, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - On Quest \'Filling the Soul Gem\' Finished - Run Script');
DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` IN (253000, 253001));
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(253000, 9, 0, 0, 0, 0, 100, 0, 100, 100, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 18, 6, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - Actionlist - Set Orientation Closest Player'),
(253000, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - Actionlist - Say Line 0'),
(253000, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 75, 18970, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - Actionlist - Add Aura \'Self Stun - (Visual only)\''),
(253000, 9, 3, 0, 0, 0, 100, 0, 60000, 60000, 0, 0, 0, 28, 18970, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - Actionlist - Remove Aura \'Self Stun - (Visual only)\''),
(253000, 9, 4, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 2, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - Actionlist - Set Faction 28'),
(253001, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 2, 28, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - Actionlist - Set Faction 28'),
(253001, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 28, 18970, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Yenniku - Actionlist - Remove Aura \'Self Stun - (Visual only)\'');
@@ -0,0 +1,12 @@
-- DB update 2023_06_29_02 -> 2023_06_30_00
--
UPDATE `creature_loot_template` SET `Chance` = 0, `GroupId` = 1 WHERE (`Entry` = 20303);
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 18478);
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
(18478, 0, 0, 0, 0, 0, 100, 0, 8500, 16800, 10900, 24100, 0, 11, 16856, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Avatar of the Martyred - In Combat - Cast \'Mortal Strike\''),
(18478, 0, 1, 0, 0, 0, 100, 0, 6500, 11500, 6200, 15700, 0, 11, 16145, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Avatar of the Martyred - In Combat - Cast \'Sunder Armor\''),
(18478, 0, 2, 0, 1, 0, 100, 512, 30000, 30000, 30000, 30000, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Avatar of the Martyred - Out of Combat - Despawn After 30s'),
(18478, 0, 3, 4, 54, 0, 100, 0, 0, 0, 0, 0, 0, 11, 33422, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Avatar of the Martyred - On Just Summoned - Cast \'Phase In\''),
(18478, 0, 4, 5, 61, 0, 100, 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Avatar of the Martyred - On Just Summoned - Set In Combat With Zone'),
(18478, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 116, 900, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Avatar of the Martyred - On Just Summoned - Set Corpse Delay to 15 Minutes');
@@ -0,0 +1,4 @@
-- DB update 2023_06_30_00 -> 2023_07_02_00
--
UPDATE `smart_scripts` SET `event_param5`=5000 WHERE `entryorguid` = 16420 AND `source_type` = 0 AND `id`=0;
UPDATE `smart_scripts` SET `event_param5`=1000 WHERE `entryorguid` = 30085 AND `source_type` = 0 AND `id` = 1;
+17 -28
View File
@@ -113,7 +113,6 @@ bool LoadRealmInfo(Acore::Asio::IoContext& ioContext);
AsyncAcceptor* StartRaSocketAcceptor(Acore::Asio::IoContext& ioContext);
void ShutdownCLIThread(std::thread* cliThread);
void AuctionListingRunnable();
void ShutdownAuctionListingThread(std::thread* thread);
void WorldUpdateLoop();
variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& cfg_service);
@@ -399,9 +398,9 @@ int main(int argc, char** argv)
cliThread.reset(new std::thread(CliThread), &ShutdownCLIThread);
}
// Launch CliRunnable thread
std::shared_ptr<std::thread> auctionLisingThread;
auctionLisingThread.reset(new std::thread(AuctionListingRunnable),
// Launch auction listing thread
std::shared_ptr<std::thread> auctionListingThread;
auctionListingThread.reset(new std::thread(AuctionListingRunnable),
[](std::thread* thr)
{
thr->join();
@@ -729,35 +728,35 @@ void AuctionListingRunnable()
while (!World::IsStopped())
{
if (AsyncAuctionListingMgr::IsAuctionListingAllowed())
{
uint32 diff = AsyncAuctionListingMgr::GetDiff();
Milliseconds diff = AsyncAuctionListingMgr::GetDiff();
AsyncAuctionListingMgr::ResetDiff();
if (AsyncAuctionListingMgr::GetTempList().size() || AsyncAuctionListingMgr::GetList().size())
if (!AsyncAuctionListingMgr::GetTempList().empty() || !AsyncAuctionListingMgr::GetList().empty())
{
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetLock());
{
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
for (auto const& delayEvent : AsyncAuctionListingMgr::GetTempList())
for (auto const& delayEvent: AsyncAuctionListingMgr::GetTempList())
AsyncAuctionListingMgr::GetList().emplace_back(delayEvent);
AsyncAuctionListingMgr::GetTempList().clear();
}
for (auto& itr : AsyncAuctionListingMgr::GetList())
for (auto& itr: AsyncAuctionListingMgr::GetList())
{
if (itr._msTimer <= diff)
itr._msTimer = 0;
if (itr._pickupTimer <= diff)
{
itr._pickupTimer = Milliseconds::zero();
}
else
itr._msTimer -= diff;
{
itr._pickupTimer -= diff;
}
}
for (std::list<AuctionListItemsDelayEvent>::iterator itr = AsyncAuctionListingMgr::GetList().begin(); itr != AsyncAuctionListingMgr::GetList().end(); ++itr)
for (auto itr = AsyncAuctionListingMgr::GetList().begin(); itr != AsyncAuctionListingMgr::GetList().end(); ++itr)
{
if ((*itr)._msTimer != 0)
if ((*itr)._pickupTimer != Milliseconds::zero())
continue;
if ((*itr).Execute())
@@ -766,22 +765,12 @@ void AuctionListingRunnable()
break;
}
}
}
std::this_thread::sleep_for(1ms);
}
LOG_INFO("server", "Auction House Listing thread exiting without problems.");
}
void ShutdownAuctionListingThread(std::thread* thread)
{
if (thread)
{
thread->join();
delete thread;
}
}
variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [[maybe_unused]] std::string& configService)
{
options_description all("Allowed options");
@@ -791,7 +780,7 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [
("dry-run,d", "Dry run")
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_CORE_CONFIG))), "use <arg> as configuration file");
#if AC_PLATFORM == WARHEAD_PLATFORM_WINDOWS
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
options_description win("Windows platform specific options");
win.add_options()
("service,s", value<std::string>(&configService)->default_value(""), "Windows service options: [install | uninstall]");
@@ -3843,6 +3843,13 @@ ChangeFaction.MaxMoney = 0
Pet.RankMod.Health = 1
#
# AuctionHouse.SearchTimeout
# Description: Time (in milliseconds) after which an auction house search is discarded.
# Default: 1000 - (1 second)
AuctionHouse.SearchTimeout = 1000
#
###################################################################################################
+146 -16
View File
@@ -988,7 +988,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
if (!IsSmart())
break;
if (targets.empty())
if (e.target.type == SMART_TARGET_NONE || e.target.type == SMART_TARGET_SELF)
{
CAST_AI(SmartAI, me->AI())->StopFollow(false);
break;
@@ -1644,6 +1644,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
}
if (e.action.orientation.turnAngle)
{
float turnOri = me->GetOrientation() + (static_cast<float>(e.action.orientation.turnAngle) * M_PI / 180.0f);
me->SetFacingTo(turnOri);
if (e.action.orientation.quickChange)
me->SetOrientation(turnOri);
break;
}
if (e.GetTargetType() == SMART_TARGET_SELF)
{
me->SetFacingTo((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation());
@@ -2824,6 +2833,48 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
break;
}
case SMART_ACTION_SET_SCALE:
{
float scale = static_cast<float>(e.action.setScale.scale) / 100.0f;
for (WorldObject* target : targets)
{
if (IsUnit(target))
{
target->ToUnit()->SetObjectScale(scale);
}
}
break;
}
case SMART_ACTION_SUMMON_RADIAL:
{
if (!me)
break;
TempSummonType spawnType = (e.action.radialSummon.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN;
float startAngle = me->GetOrientation() + (static_cast<float>(e.action.radialSummon.startAngle) * M_PI / 180.0f);
float stepAngle = static_cast<float>(e.action.radialSummon.stepAngle) * M_PI / 180.0f;
if (e.action.radialSummon.dist)
{
for (uint32 itr = 0; itr < e.action.radialSummon.repetitions; itr++)
{
Position summonPos = me->GetPosition();
summonPos.RelocatePolarOffset(itr * stepAngle, static_cast<float>(e.action.radialSummon.dist));
me->SummonCreature(e.action.radialSummon.summonEntry, summonPos, spawnType, e.action.radialSummon.summonDuration);
}
break;
}
for (uint32 itr = 0; itr < e.action.radialSummon.repetitions; itr++)
{
float currentAngle = startAngle + (itr * stepAngle);
me->SummonCreature(e.action.radialSummon.summonEntry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), currentAngle, spawnType, e.action.radialSummon.summonDuration);
}
break;
}
default:
LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry {} SourceType {}, Event {}, Unhandled Action type {}", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
break;
@@ -4157,34 +4208,105 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
break;
case SMART_EVENT_NEAR_PLAYERS:
{
ObjectVector units;
GetWorldObjectsInDist(units, static_cast<float>(e.event.nearPlayer.radius));
uint32 playerCount = 0;
ObjectVector targets;
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearPlayer.radius));
if (!units.empty())
if (!targets.empty())
{
if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
return;
for (WorldObject* target : targets)
{
if (IsPlayer(target))
playerCount++;
if (units.size() >= e.event.nearPlayer.minCount)
ProcessAction(e, unit);
if (playerCount >= e.event.nearPlayer.minCount)
ProcessAction(e, target->ToUnit());
}
RecalcTimer(e, e.event.nearPlayer.checkTimer, e.event.nearPlayer.checkTimer);
}
RecalcTimer(e, e.event.nearPlayer.repeatMin, e.event.nearPlayer.repeatMax);
break;
}
case SMART_EVENT_NEAR_PLAYERS_NEGATION:
{
ObjectVector units;
GetWorldObjectsInDist(units, static_cast<float>(e.event.nearPlayerNegation.radius));
uint32 playerCount = 0;
ObjectVector targets;
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearPlayerNegation.radius));
if (!units.empty())
if (!targets.empty())
{
if (!unit || unit->GetTypeId() != TYPEID_PLAYER)
return;
for (WorldObject* target : targets)
{
if (IsPlayer(target))
playerCount++;
}
if (units.size() < e.event.nearPlayerNegation.minCount)
if (playerCount <= e.event.nearPlayerNegation.maxCount)
ProcessAction(e, unit);
}
RecalcTimer(e, e.event.nearPlayerNegation.checkTimer, e.event.nearPlayerNegation.checkTimer);
RecalcTimer(e, e.event.nearPlayerNegation.repeatMin, e.event.nearPlayerNegation.repeatMax);
break;
}
case SMART_EVENT_NEAR_UNIT:
{
uint32 unitCount = 0;
ObjectVector targets;
GetWorldObjectsInDist(targets, static_cast<float>(e.event.nearUnit.range));
if (!targets.empty())
{
if (e.event.nearUnit.type)
{
for (WorldObject* target : targets)
{
if (IsGameObject(target) && target->GetEntry() == e.event.nearUnit.entry)
unitCount++;
}
}
else
{
for (WorldObject* target : targets)
{
if (IsCreature(target) && target->GetEntry() == e.event.nearUnit.entry)
unitCount++;
}
}
if (unitCount >= e.event.nearUnit.count)
ProcessAction(e, unit);
}
RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer);
break;
}
case SMART_EVENT_AREA_CASTING:
{
if (!me || !me->IsEngaged())
return;
float range = static_cast<float>(e.event.areaCasting.range);
ThreatContainer::StorageType threatList = me->GetThreatMgr().GetThreatList();
for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
{
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
{
if (e.event.areaCasting.range && !me->IsWithinDistInMap(target, range))
continue;
if (!target || !target->IsNonMeleeSpellCast(false, false, true))
continue;
if (e.event.areaCasting.spellId > 0)
if (Spell* currSpell = target->GetCurrentSpell(CURRENT_GENERIC_SPELL))
if (currSpell->m_spellInfo->Id != e.event.areaCasting.spellId)
continue;
ProcessAction(e, target);
RecalcTimer(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMin);
return;
}
}
// If no targets are found and it's off cooldown, check again
RecalcTimer(e, e.event.areaCasting.checkTimer, e.event.areaCasting.checkTimer);
break;
}
default:
@@ -4223,6 +4345,12 @@ void SmartScript::InitTimer(SmartScriptHolder& e)
case SMART_EVENT_DISTANCE_GAMEOBJECT:
RecalcTimer(e, e.event.distance.repeat, e.event.distance.repeat);
break;
case SMART_EVENT_NEAR_UNIT:
RecalcTimer(e, e.event.nearUnit.timer, e.event.nearUnit.timer);
break;
case SMART_EVENT_AREA_CASTING:
RecalcTimer(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax);
break;
default:
e.active = true;
break;
@@ -4276,6 +4404,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
{
case SMART_EVENT_NEAR_PLAYERS:
case SMART_EVENT_NEAR_PLAYERS_NEGATION:
case SMART_EVENT_NEAR_UNIT:
case SMART_EVENT_UPDATE:
case SMART_EVENT_UPDATE_OOC:
case SMART_EVENT_UPDATE_IC:
@@ -4285,6 +4414,7 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff)
case SMART_EVENT_TARGET_MANA_PCT:
case SMART_EVENT_RANGE:
case SMART_EVENT_VICTIM_CASTING:
case SMART_EVENT_AREA_CASTING:
case SMART_EVENT_FRIENDLY_HEALTH:
case SMART_EVENT_FRIENDLY_IS_CC:
case SMART_EVENT_FRIENDLY_MISSING_BUFF:
@@ -280,6 +280,10 @@ void SmartAIMgr::LoadSmartAIFromDB()
if (temp.event.minMaxRepeat.min == 0 && temp.event.minMaxRepeat.max == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break;
case SMART_EVENT_AREA_CASTING:
if (temp.event.areaCasting.repeatMin == 0 && temp.event.areaCasting.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
break;
case SMART_EVENT_FRIENDLY_IS_CC:
if (temp.event.friendlyCC.repeatMin == 0 && temp.event.friendlyCC.repeatMax == 0)
temp.event.event_flags |= SMART_EVENT_FLAG_NOT_REPEATABLE;
@@ -346,10 +350,12 @@ void SmartAIMgr::LoadSmartAIFromDB()
case SMART_EVENT_TARGET_MANA_PCT:
case SMART_EVENT_RANGE:
case SMART_EVENT_VICTIM_CASTING:
case SMART_EVENT_AREA_CASTING:
case SMART_EVENT_TARGET_BUFFED:
case SMART_EVENT_IS_BEHIND_TARGET:
case SMART_EVENT_INSTANCE_PLAYER_ENTER:
case SMART_EVENT_TRANSPORT_ADDCREATURE:
case SMART_EVENT_NEAR_PLAYERS:
return true;
default:
return false;
@@ -572,6 +578,8 @@ bool SmartAIMgr::CheckUnusedEventParams(SmartScriptHolder const& e)
case SMART_EVENT_SUMMONED_UNIT_DIES: return sizeof(SmartEvent::summoned);
case SMART_EVENT_NEAR_PLAYERS: return sizeof(SmartEvent::nearPlayer);
case SMART_EVENT_NEAR_PLAYERS_NEGATION: return sizeof(SmartEvent::nearPlayerNegation);
case SMART_EVENT_NEAR_UNIT: return sizeof(SmartEvent::nearUnit);
case SMART_EVENT_AREA_CASTING: return sizeof(SmartEvent::areaCasting);
default:
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an event {} with no unused params specified in SmartAIMgr::CheckUnusedEventParams(), please report this.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.GetEventType());
@@ -671,7 +679,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
case SMART_ACTION_SET_COUNTER: return sizeof(SmartAction::setCounter);
case SMART_ACTION_STORE_TARGET_LIST: return sizeof(SmartAction::storeTargets);
case SMART_ACTION_WP_RESUME: return NO_PARAMS;
case SMART_ACTION_SET_ORIENTATION: return NO_PARAMS;
case SMART_ACTION_SET_ORIENTATION: return sizeof(SmartAction::orientation);
case SMART_ACTION_CREATE_TIMED_EVENT: return sizeof(SmartAction::timeEvent);
case SMART_ACTION_PLAYMOVIE: return sizeof(SmartAction::movie);
case SMART_ACTION_MOVE_TO_POS: return sizeof(SmartAction::moveToPos);
@@ -763,6 +771,8 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
case SMART_ACTION_MUSIC: return sizeof(SmartAction::music);
case SMART_ACTION_SET_GUID: return sizeof(SmartAction::setGuid);
case SMART_ACTION_DISABLE: return sizeof(SmartAction::disable);
case SMART_ACTION_SET_SCALE: return sizeof(SmartAction::setScale);
case SMART_ACTION_SUMMON_RADIAL: return sizeof(SmartAction::radialSummon);
default:
LOG_WARN("sql.sql", "SmartAIMgr: entryorguid {} source_type {} id {} action_type {} is using an action with no unused params specified in SmartAIMgr::CheckUnusedActionParams(), please report this.",
e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType());
@@ -1041,6 +1051,16 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
if (!IsMinMaxValid(e, e.event.targetCasting.repeatMin, e.event.targetCasting.repeatMax))
return false;
break;
case SMART_EVENT_AREA_CASTING:
if (e.event.areaCasting.spellId > 0 && !sSpellMgr->GetSpellInfo(e.event.areaCasting.spellId))
{
LOG_ERROR("scripts.ai.sai", "SmartAIMgr: Entry {} SourceType {} Event {} Action {} uses non-existent Spell entry {}, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.event.spellHit.spell);
return false;
}
if (!IsMinMaxValid(e, e.event.areaCasting.repeatMin, e.event.areaCasting.repeatMax))
return false;
break;
case SMART_EVENT_PASSENGER_BOARDED:
case SMART_EVENT_PASSENGER_REMOVED:
if (!IsMinMaxValid(e, e.event.minMax.repeatMin, e.event.minMax.repeatMax))
@@ -1270,6 +1290,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_EVENT_GO_EVENT_INFORM:
case SMART_EVENT_NEAR_PLAYERS:
case SMART_EVENT_NEAR_PLAYERS_NEGATION:
if (!IsMinMaxValid(e, e.event.nearPlayer.repeatMin, e.event.nearPlayer.repeatMax))
return false;
break;
case SMART_EVENT_NEAR_UNIT:
case SMART_EVENT_TIMED_EVENT_TRIGGERED:
case SMART_EVENT_INSTANCE_PLAYER_ENTER:
case SMART_EVENT_TRANSPORT_RELOCATE:
@@ -1920,6 +1944,8 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e)
case SMART_ACTION_PLAY_CINEMATIC:
case SMART_ACTION_SET_GUID:
case SMART_ACTION_DISABLE:
case SMART_ACTION_SET_SCALE:
case SMART_ACTION_SUMMON_RADIAL:
break;
default:
LOG_ERROR("sql.sql", "SmartAIMgr: Not handled action_type({}), event_type({}), Entry {} SourceType {} Event {}, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id);
@@ -206,10 +206,12 @@ enum SMART_EVENT
/* AC Custom Events */
SMART_EVENT_AC_START = 100,
SMART_EVENT_NEAR_PLAYERS = 101, // min, radius, first timer, check timer
SMART_EVENT_NEAR_PLAYERS_NEGATION = 102, // min, radius, first timer, check timer
SMART_EVENT_NEAR_PLAYERS = 101, // min, radius, first timer, repeatMin, repeatMax
SMART_EVENT_NEAR_PLAYERS_NEGATION = 102, // max, radius, first timer, repeatMin, repeatMax
SMART_EVENT_NEAR_UNIT = 103, // type (0: creature 1: gob), entry, count, range, timer
SMART_EVENT_AREA_CASTING = 104, // spellId (0: any), range (0: any), repeatMin, repeatMax, checkTimer
SMART_EVENT_AC_END = 103
SMART_EVENT_AC_END = 105
};
struct SmartEvent
@@ -482,17 +484,37 @@ struct SmartEvent
uint32 minCount;
uint32 radius;
uint32 firstTimer;
uint32 checkTimer;
uint32 repeatMin;
uint32 repeatMax;
} nearPlayer;
struct
{
uint32 minCount;
uint32 maxCount;
uint32 radius;
uint32 firstTimer;
uint32 checkTimer;
uint32 repeatMin;
uint32 repeatMax;
} nearPlayerNegation;
struct
{
uint32 type;
uint32 entry;
uint32 count;
uint32 range;
uint32 timer;
} nearUnit;
struct
{
uint32 spellId;
uint32 range;
uint32 repeatMin;
uint32 repeatMax;
uint32 checkTimer;
} areaCasting;
struct
{
uint32 param1;
@@ -588,7 +610,7 @@ enum SMART_ACTION
SMART_ACTION_SET_COUNTER = 63, // id, value, reset (0/1)
SMART_ACTION_STORE_TARGET_LIST = 64, // varID,
SMART_ACTION_WP_RESUME = 65, // none
SMART_ACTION_SET_ORIENTATION = 66, // quick change, random orientation? (0/1)
SMART_ACTION_SET_ORIENTATION = 66, // quick change, random orientation? (0/1), turnAngle
SMART_ACTION_CREATE_TIMED_EVENT = 67, // id, InitialMin, InitialMax, RepeatMin(only if it repeats), RepeatMax(only if it repeats), chance
SMART_ACTION_PLAYMOVIE = 68, // entry
SMART_ACTION_MOVE_TO_POS = 69, // PointId (optional x,y,z offset), transport, controlled, ContactDistance
@@ -693,9 +715,11 @@ enum SMART_ACTION
SMART_ACTION_DO_ACTION = 223, // ActionId
SMART_ACTION_ATTACK_STOP = 224, //
SMART_ACTION_SET_GUID = 225, // Sends the invoker's or the base object's own ObjectGuid to target
SMART_ACTION_DISABLE = 226, // Disable the targeted creatures, setting them Invisible and Immune to All
SMART_ACTION_DISABLE = 226, // state
SMART_ACTION_SET_SCALE = 227, // scale
SMART_ACTION_SUMMON_RADIAL = 228, // summonEntry, summonDuration, repetitions, startAngle, stepAngle, dist
SMART_ACTION_AC_END = 227, // placeholder
SMART_ACTION_AC_END = 229, // placeholder
};
enum class SmartActionSummonCreatureFlags
@@ -1289,6 +1313,7 @@ struct SmartAction
{
uint32 quickChange;
uint32 random;
uint32 turnAngle;
} orientation;
struct
@@ -1376,6 +1401,21 @@ struct SmartAction
{
SAIBool state;
} disable;
struct
{
uint32 scale;
} setScale;
struct
{
uint32 summonEntry;
uint32 summonDuration;
uint32 repetitions;
uint32 startAngle;
uint32 stepAngle;
uint32 dist;
} radialSummon;
//! Note for any new future actions
//! All parameters must have type uint32
@@ -1777,8 +1817,10 @@ const uint32 SmartAIEventMask[SMART_EVENT_AC_END][2] =
{ 0, 0 }, // 98
{ 0, 0 }, // 99
{ 0, 0 }, // 100
{SMART_EVENT_NEAR_PLAYERS, SMART_SCRIPT_TYPE_MASK_CREATURE },
{SMART_EVENT_NEAR_PLAYERS_NEGATION, SMART_SCRIPT_TYPE_MASK_CREATURE }
{SMART_EVENT_NEAR_PLAYERS, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_NEAR_PLAYERS_NEGATION, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_NEAR_UNIT, SMART_SCRIPT_TYPE_MASK_CREATURE + SMART_SCRIPT_TYPE_MASK_GAMEOBJECT },
{SMART_EVENT_AREA_CASTING, SMART_SCRIPT_TYPE_MASK_CREATURE }
};
enum SmartEventFlags
@@ -2394,6 +2394,11 @@ bool AchievementMgr::CanUpdateCriteria(AchievementCriteriaEntry const* criteria,
return true;
}
CompletedAchievementMap const& AchievementMgr::GetCompletedAchievements()
{
return _completedAchievements;
}
AchievementGlobalMgr* AchievementGlobalMgr::instance()
{
static AchievementGlobalMgr instance;
@@ -300,6 +300,7 @@ public:
void RemoveCriteriaProgress(AchievementCriteriaEntry const* entry);
CriteriaProgress* GetCriteriaProgress(AchievementCriteriaEntry const* entry);
CompletedAchievementMap const& GetCompletedAchievements();
private:
enum ProgressType { PROGRESS_SET, PROGRESS_ACCUMULATE, PROGRESS_HIGHEST, PROGRESS_RESET };
@@ -727,7 +727,7 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player,
bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& wsearchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder)
uint32& count, uint32& totalcount, uint8 /*getAll*/, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout)
{
uint32 itrcounter = 0;
@@ -753,17 +753,14 @@ bool AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
int locdbc_idx = player->GetSession()->GetSessionDbcLocale();
for (AuctionEntryMap::const_iterator itr = _auctionsMap.begin(); itr != _auctionsMap.end(); ++itr)
{
if (!AsyncAuctionListingMgr::IsAuctionListingAllowed()) // pussywizard: World::Update is waiting for us...
{
if ((itrcounter++) % 100 == 0) // check condition every 100 iterations
{
if (sWorldUpdateTime.GetAverageUpdateTime() >= 30 || GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= 10ms) // pussywizard: stop immediately if diff is high or waiting too long
if (GetMSTimeDiff(GameTime::GetGameTimeMS(), GetTimeMS()) >= searchTimeout) // pussywizard: stop immediately if diff is high or waiting too long
{
return false;
}
}
}
AuctionEntry* Aentry = itr->second;
// Skip expired auctions
@@ -162,7 +162,7 @@ public:
bool BuildListAuctionItems(WorldPacket& data, Player* player,
std::wstring const& searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax, uint8 usable,
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder);
uint32& count, uint32& totalcount, uint8 getAll, AuctionSortOrderVector const& sortOrder, Milliseconds searchTimeout);
private:
AuctionEntryMap _auctionsMap;
@@ -184,7 +184,6 @@ public:
AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId);
AuctionHouseObject* GetAuctionsMapByHouseId(uint8 auctionHouseId);
AuctionHouseObject* GetBidsMap(uint32 factionTemplateId);
Item* GetAItem(ObjectGuid itemGuid)
{
@@ -174,11 +174,11 @@ void KillRewarder::_RewardXP(Player* player, float rate)
}
}
void KillRewarder::_RewardReputation(Player* player, float rate)
void KillRewarder::_RewardReputation(Player* player)
{
// 4.3. Give reputation (player must not be on BG).
// Even dead players and corpses are rewarded.
player->RewardReputation(_victim, rate);
player->RewardReputation(_victim);
}
void KillRewarder::_RewardKillCredit(Player* player)
@@ -208,7 +208,6 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
if (!_isPvP || _isBattleGround)
{
float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
float reputationRate = _group ? _groupRate * float(player->GetLevel()) / _sumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
sScriptMgr->OnRewardKillRewarder(player, isDungeon, xpRate); // Personal rate is 100%.
if (_xp)
@@ -219,7 +218,7 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
if (!_isBattleGround)
{
// If killer is in dungeon then all members receive full reputation at kill.
_RewardReputation(player, isDungeon ? 1.0f : reputationRate);
_RewardReputation(player);
_RewardKillCredit(player);
}
}
@@ -37,7 +37,7 @@ private:
void _RewardHonor(Player* player);
void _RewardXP(Player* player, float rate);
void _RewardReputation(Player* player, float rate);
void _RewardReputation(Player* player);
void _RewardKillCredit(Player* player);
void _RewardPlayer(Player* player, bool isDungeon);
void _RewardGroup();
+4 -3
View File
@@ -5858,7 +5858,7 @@ float Player::CalculateReputationGain(ReputationSource source, uint32 creatureOr
}
// Calculates how many reputation points player gains in victim's enemy factions
void Player::RewardReputation(Unit* victim, float rate)
void Player::RewardReputation(Unit* victim)
{
if (!victim || victim->GetTypeId() == TYPEID_PLAYER)
return;
@@ -5887,7 +5887,6 @@ void Player::RewardReputation(Unit* victim, float rate)
if (Rep->RepFaction1 && (!Rep->TeamDependent || teamId == TEAM_ALLIANCE))
{
float donerep1 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->GetLevel(), static_cast<float>(Rep->RepValue1), ChampioningFaction ? ChampioningFaction : Rep->RepFaction1);
donerep1 *= rate;
FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction1);
if (factionEntry1)
@@ -5899,7 +5898,6 @@ void Player::RewardReputation(Unit* victim, float rate)
if (Rep->RepFaction2 && (!Rep->TeamDependent || teamId == TEAM_HORDE))
{
float donerep2 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->GetLevel(), static_cast<float>(Rep->RepValue2), ChampioningFaction ? ChampioningFaction : Rep->RepFaction2);
donerep2 *= rate;
FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction2);
if (factionEntry2)
@@ -13443,8 +13441,11 @@ LootItem* Player::StoreLootItem(uint8 lootSlot, Loot* loot, InventoryResult& msg
LootItem* item = loot->LootItemInSlot(lootSlot, this, &qitem, &ffaitem, &conditem);
if (!item || item->is_looted)
{
if (!sScriptMgr->CanSendErrorAlreadyLooted(this))
{
SendEquipError(EQUIP_ERR_ALREADY_LOOTED, nullptr, nullptr);
}
return nullptr;
}
+1 -1
View File
@@ -2086,7 +2086,7 @@ public:
ReputationMgr& GetReputationMgr() { return *m_reputationMgr; }
[[nodiscard]] ReputationMgr const& GetReputationMgr() const { return *m_reputationMgr; }
[[nodiscard]] ReputationRank GetReputationRank(uint32 faction_id) const;
void RewardReputation(Unit* victim, float rate);
void RewardReputation(Unit* victim);
void RewardReputation(Quest const* quest);
float CalculateReputationGain(ReputationSource source, uint32 creatureOrQuestLevel, float rep, int32 faction, bool noQuestBonus = false);
@@ -668,23 +668,24 @@ void WorldSession::HandleAuctionListOwnerItems(WorldPacket& recvData)
recvData >> listfrom; // not used in fact (this list does not have page control in client)
// pussywizard:
const uint32 delay = 4500;
const uint32 now = GameTime::GetGameTimeMS().count();
const Milliseconds now = GameTime::GetGameTimeMS();
if (_lastAuctionListOwnerItemsMSTime > now) // list is pending
return;
uint32 diff = getMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);
const Milliseconds delay = Milliseconds(4500);
Milliseconds diff = GetMSTimeDiff(_lastAuctionListOwnerItemsMSTime, now);
if (diff > delay)
diff = delay;
_lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual exectuing will change this to getMSTime of that moment
_player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID(), true), _player->m_Events.CalculateTime(delay - diff));
_lastAuctionListOwnerItemsMSTime = now + delay; // set longest possible here, actual executing will change this to getMSTime of that moment
_player->m_Events.AddEvent(new AuctionListOwnerItemsDelayEvent(guid, _player->GetGUID()), _player->m_Events.CalculateTime(delay.count() - diff.count()));
}
void WorldSession::HandleAuctionListOwnerItemsEvent(ObjectGuid creatureGuid)
{
LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_LIST_OWNER_ITEMS");
_lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS().count(); // pussywizard
_lastAuctionListOwnerItemsMSTime = GameTime::GetGameTimeMS(); // pussywizard
Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(creatureGuid, UNIT_NPC_FLAG_AUCTIONEER);
if (!creature)
@@ -757,17 +758,17 @@ void WorldSession::HandleAuctionListItems(WorldPacket& recvData)
}
// pussywizard:
const uint32 delay = 2000;
const uint32 now = GameTime::GetGameTimeMS().count();
uint32 diff = getMSTimeDiff(_lastAuctionListItemsMSTime, now);
const Milliseconds delay = 2s;
const Milliseconds now = GameTime::GetGameTimeMS();
Milliseconds diff = GetMSTimeDiff(_lastAuctionListItemsMSTime, now);
if (diff > delay)
{
diff = delay;
}
_lastAuctionListItemsMSTime = now + delay - diff;
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetTempLock());
AsyncAuctionListingMgr::GetTempList().push_back(AuctionListItemsDelayEvent(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder));
AsyncAuctionListingMgr::GetTempList().emplace_back(delay - diff, _player->GetGUID(), guid, searchedname, listfrom, levelmin, levelmax, usable, auctionSlotID,
auctionMainCategory, auctionSubCategory, quality, getAll, sortOrder);
}
void WorldSession::HandleAuctionListPendingSales(WorldPacket& recvData)
+3
View File
@@ -93,6 +93,8 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
loot = &creature->loot;
}
sScriptMgr->OnAfterCreatureLoot(player);
InventoryResult msg;
LootItem* lootItem = player->StoreLootItem(lootSlot, loot, msg);
if (msg != EQUIP_ERR_OK && lguid.IsItem() && loot->loot_type != LOOT_CORPSE)
@@ -209,6 +211,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
}
else
{
sScriptMgr->OnAfterCreatureLootMoney(player);
player->ModifyMoney(loot->gold);
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY, loot->gold);
+6 -7
View File
@@ -22,11 +22,9 @@
#include "Player.h"
#include "SpellAuraEffects.h"
uint32 AsyncAuctionListingMgr::auctionListingDiff = 0;
bool AsyncAuctionListingMgr::auctionListingAllowed = false;
Milliseconds AsyncAuctionListingMgr::auctionListingDiff = Milliseconds::zero();
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingList;
std::list<AuctionListItemsDelayEvent> AsyncAuctionListingMgr::auctionListingListTemp;
std::mutex AsyncAuctionListingMgr::auctionListingLock;
std::mutex AsyncAuctionListingMgr::auctionListingTempLock;
bool AuctionListOwnerItemsDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
@@ -60,18 +58,19 @@ bool AuctionListItemsDelayEvent::Execute()
wstrToLower(wsearchedname);
uint32 searchTimeout = sWorld->getIntConfig(CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT);
bool result = auctionHouse->BuildListAuctionItems(data, plr,
wsearchedname, _listfrom, _levelmin, _levelmax, _usable,
_auctionSlotID, _auctionMainCategory, _auctionSubCategory, _quality,
count, totalcount, _getAll, _sortOrder);
if (!result)
return false;
count, totalcount, _getAll, _sortOrder, Milliseconds(searchTimeout));
if (result)
{
data.put<uint32>(0, count);
data << (uint32) totalcount;
data << (uint32) 300; // clientside search cooldown [ms] (gray search button)
plr->GetSession()->SendPacket(&data);
}
return true;
}
+8 -16
View File
@@ -25,30 +25,28 @@
class AuctionListOwnerItemsDelayEvent : public BasicEvent
{
public:
AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid, bool o) : creatureGuid(_creatureGuid), playerguid(guid), owner(o) {}
AuctionListOwnerItemsDelayEvent(ObjectGuid _creatureGuid, ObjectGuid guid) : creatureGuid(_creatureGuid), playerguid(guid) {}
~AuctionListOwnerItemsDelayEvent() override {}
bool Execute(uint64 e_time, uint32 p_time) override;
void Abort(uint64 /*e_time*/) override {}
bool getOwner() { return owner; }
private:
ObjectGuid creatureGuid;
ObjectGuid playerguid;
bool owner;
};
class AuctionListItemsDelayEvent
{
public:
AuctionListItemsDelayEvent(uint32 msTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax,
AuctionListItemsDelayEvent(Milliseconds pickupTimer, ObjectGuid playerguid, ObjectGuid creatureguid, std::string searchedname, uint32 listfrom, uint8 levelmin, uint8 levelmax,
uint8 usable, uint32 auctionSlotID, uint32 auctionMainCategory, uint32 auctionSubCategory, uint32 quality, uint8 getAll, AuctionSortOrderVector sortOrder) :
_msTimer(msTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax),_usable(usable),
_pickupTimer(pickupTimer), _playerguid(playerguid), _creatureguid(creatureguid), _searchedname(searchedname), _listfrom(listfrom), _levelmin(levelmin), _levelmax(levelmax),_usable(usable),
_auctionSlotID(auctionSlotID), _auctionMainCategory(auctionMainCategory), _auctionSubCategory(auctionSubCategory), _quality(quality), _getAll(getAll), _sortOrder(sortOrder) { }
bool Execute();
uint32 _msTimer;
Milliseconds _pickupTimer;
ObjectGuid _playerguid;
ObjectGuid _creatureguid;
std::string _searchedname;
@@ -67,23 +65,17 @@ public:
class AsyncAuctionListingMgr
{
public:
static void Update(uint32 diff) { auctionListingDiff += diff; }
static uint32 GetDiff() { return auctionListingDiff; }
static void ResetDiff() { auctionListingDiff = 0; }
static bool IsAuctionListingAllowed() { return auctionListingAllowed; }
static void SetAuctionListingAllowed(bool a) { auctionListingAllowed = a; }
static void Update(Milliseconds diff) { auctionListingDiff += diff; }
static Milliseconds GetDiff() { return auctionListingDiff; }
static void ResetDiff() { auctionListingDiff = Milliseconds::zero(); }
static std::list<AuctionListItemsDelayEvent>& GetList() { return auctionListingList; }
static std::list<AuctionListItemsDelayEvent>& GetTempList() { return auctionListingListTemp; }
static std::mutex& GetLock() { return auctionListingLock; }
static std::mutex& GetTempLock() { return auctionListingTempLock; }
private:
static uint32 auctionListingDiff;
static bool auctionListingAllowed;
static Milliseconds auctionListingDiff;
static std::list<AuctionListItemsDelayEvent> auctionListingList;
static std::list<AuctionListItemsDelayEvent> auctionListingListTemp;
static std::mutex auctionListingLock;
static std::mutex auctionListingTempLock;
};
@@ -913,6 +913,37 @@ bool ScriptMgr::CanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid
return true;
}
bool ScriptMgr::CanSendErrorAlreadyLooted(Player* player)
{
auto ret = IsValidBoolScript<PlayerScript>([&](PlayerScript* script)
{
return !script->CanSendErrorAlreadyLooted(player);
});
if (ret && *ret)
{
return false;
}
return true;
}
void ScriptMgr::OnAfterCreatureLoot(Player* player)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
{
script->OnAfterCreatureLoot(player);
});
}
void ScriptMgr::OnAfterCreatureLootMoney(Player* player)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
{
script->OnAfterCreatureLootMoney(player);
});
}
void ScriptMgr::PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type)
{
ExecuteScript<PlayerScript>([&](PlayerScript* script)
@@ -986,7 +1017,7 @@ void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result,
void ScriptMgr::OnUpdateGatheringSkill(Player *player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32 &gain) {
ExecuteScript<PlayerScript>([&](PlayerScript* script)
{
script->OnUpdateGatheringSkill(player, skillId, gray, green, yellow, currentLevel, gain);
script->OnUpdateGatheringSkill(player, skillId, currentLevel, gray, green, yellow, gain);
});
}
+27
View File
@@ -1483,6 +1483,30 @@ public:
virtual void AnticheatUpdateMovementInfo(Player* /*player*/, MovementInfo const& /*movementInfo*/) { }
[[nodiscard]] virtual bool AnticheatHandleDoubleJump(Player* /*player*/, Unit* /*mover*/) { return true; }
[[nodiscard]] virtual bool AnticheatCheckMovementInfo(Player* /*player*/, MovementInfo const& /*movementInfo*/, Unit* /*mover*/, bool /*jump*/) { return true; }
/**
* @brief This hook is called, to avoid displaying the error message that the body has already been stripped
*
* @param player Contains information about the Player
*
* @return true Avoiding displaying the error message that the loot has already been taken.
*/
virtual bool CanSendErrorAlreadyLooted(Player* /*player*/) { return true; }
/**
* @brief It is used when an item is taken from a creature.
*
* @param player Contains information about the Player
*
*/
virtual void OnAfterCreatureLoot(Player* /*player*/) { }
/**
* @brief After a creature's money is taken
*
* @param player Contains information about the Player
*/
virtual void OnAfterCreatureLootMoney(Player* /*player*/) { }
};
class AccountScript : public ScriptObject
@@ -2447,6 +2471,9 @@ public: /* PlayerScript */
void OnPlayerEnterCombat(Player* player, Unit* enemy);
void OnPlayerLeaveCombat(Player* player);
void OnQuestAbandon(Player* player, uint32 questId);
bool CanSendErrorAlreadyLooted(Player* player);
void OnAfterCreatureLoot(Player* player);
void OnAfterCreatureLootMoney(Player* player);
// Anti cheat
void AnticheatSetSkipOnePacketForASH(Player* player, bool apply);
+2 -2
View File
@@ -1079,8 +1079,8 @@ public: // opcodes handlers
void HandleEnterPlayerVehicle(WorldPacket& data);
void HandleUpdateProjectilePosition(WorldPacket& recvPacket);
uint32 _lastAuctionListItemsMSTime;
uint32 _lastAuctionListOwnerItemsMSTime;
Milliseconds _lastAuctionListItemsMSTime;
Milliseconds _lastAuctionListOwnerItemsMSTime;
void HandleTeleportTimeout(bool updateInSessions);
bool HandleSocketClosed();
@@ -1918,6 +1918,16 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
}
}
break;
case 34026: // Kill Command
// Dungeon Set 3
if (caster->HasAura(37483))
{
if (apply)
{
caster->CastSpell(caster, 37482, true);
}
}
break;
}
break;
case SPELLFAMILY_PALADIN:
+5
View File
@@ -3436,6 +3436,11 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
spell_bonus += int32(0.08f * m_caster->GetTotalAttackPowerValue(BASE_ATTACK));
spell_bonus += int32(0.13f * m_caster->SpellBaseDamageBonusDone(m_spellInfo->GetSchoolMask()));
break;
case 42463: // Seals of the Pure for Seal of Vengeance/Corruption
case 53739:
if (AuraEffect const* sealsOfPure = m_caster->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_PALADIN, 25, 0))
AddPct(totalDamagePercentMod, sealsOfPure->GetAmount());
break;
case 53385: // Divine Storm deals normalized damage
normalized = true;
break;
+1
View File
@@ -413,6 +413,7 @@ enum WorldIntConfigs
CONFIG_LFG_KICK_PREVENTION_TIMER,
CONFIG_CHANGE_FACTION_MAX_MONEY,
CONFIG_WATER_BREATH_TIMER,
CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT,
INT_CONFIG_VALUE_COUNT
};
+3 -15
View File
@@ -1286,6 +1286,8 @@ void World::LoadConfigSettings(bool reload)
_bool_configs[CONFIG_ALLOWS_RANK_MOD_FOR_PET_HEALTH] = sConfigMgr->GetOption<bool>("Pet.RankMod.Health", true);
_int_configs[CONFIG_AUCTION_HOUSE_SEARCH_TIMEOUT] = sConfigMgr->GetOption<uint32>("AuctionHouse.SearchTimeout", 1000);
///- Read the "Data" directory from the config file
std::string dataPath = sConfigMgr->GetOption<std::string>("DataDir", "./");
if (dataPath.empty() || (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\'))
@@ -2352,13 +2354,6 @@ void World::Update(uint32 diff)
sScriptMgr->OnPlayerbotUpdate(diff);
// pussywizard:
// acquire mutex now, this is kind of waiting for listing thread to finish it's work (since it can't process next packet)
// so we don't have to do it in every packet that modifies auctions
AsyncAuctionListingMgr::SetAuctionListingAllowed(false);
{
std::lock_guard<std::mutex> guard(AsyncAuctionListingMgr::GetLock());
// pussywizard: handle auctions when the timer has passed
if (_timers[WUPDATE_AUCTIONS].Passed())
{
@@ -2370,7 +2365,7 @@ void World::Update(uint32 diff)
sAuctionMgr->Update();
}
AsyncAuctionListingMgr::Update(diff);
AsyncAuctionListingMgr::Update(Milliseconds(diff));
if (currentGameTime > _mail_expire_check_timer)
{
@@ -2378,15 +2373,8 @@ void World::Update(uint32 diff)
_mail_expire_check_timer = currentGameTime + 6h;
}
{
/// <li> Handle session updates when the timer has passed
METRIC_TIMER("world_update_time", METRIC_TAG("type", "Update sessions"));
UpdateSessions(diff);
}
}
// end of section with mutex
AsyncAuctionListingMgr::SetAuctionListingAllowed(true);
/// <li> Handle weather updates when the timer has passed
if (_timers[WUPDATE_WEATHERS].Passed())
@@ -157,7 +157,6 @@ void AddSC_isle_of_queldanas();
void AddSC_redridge_mountains();
void AddSC_silverpine_forest();
void AddSC_stormwind_city();
void AddSC_stranglethorn_vale();
void AddSC_tirisfal_glades();
void AddSC_undercity();
void AddSC_western_plaguelands();
@@ -310,7 +309,6 @@ void AddEasternKingdomsScripts()
AddSC_redridge_mountains();
AddSC_silverpine_forest();
AddSC_stormwind_city();
AddSC_stranglethorn_vale();
AddSC_tirisfal_glades();
AddSC_undercity();
AddSC_western_plaguelands();
@@ -1,129 +0,0 @@
/*
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by the
* Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* ScriptData
SDName: Stranglethorn_Vale
SD%Complete: 100
SDComment: Quest support: 592
SDCategory: Stranglethorn Vale
EndScriptData */
/* ContentData
npc_yenniku
EndContentData */
#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellInfo.h"
/*######
## npc_yenniku
######*/
class npc_yenniku : public CreatureScript
{
public:
npc_yenniku() : CreatureScript("npc_yenniku") { }
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_yennikuAI(creature);
}
struct npc_yennikuAI : public ScriptedAI
{
npc_yennikuAI(Creature* creature) : ScriptedAI(creature)
{
bReset = false;
}
uint32 Reset_Timer;
bool bReset;
void Reset() override
{
Reset_Timer = 0;
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
}
void SpellHit(Unit* caster, SpellInfo const* spell) override
{
if (bReset || spell->Id != 3607)
return;
if (Player* player = caster->ToPlayer())
{
if (player->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE) //Yenniku's Release
{
me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN);
me->CombatStop(); //stop combat
me->GetThreatMgr().ClearAllThreat(); //unsure of this
me->SetFaction(FACTION_HORDE_GENERIC);
bReset = true;
Reset_Timer = 60000;
}
}
}
void JustEngagedWith(Unit* /*who*/) override { }
void UpdateAI(uint32 diff) override
{
if (bReset)
{
if (Reset_Timer <= diff)
{
EnterEvadeMode();
bReset = false;
me->SetFaction(FACTION_TROLL_BLOODSCALP);
return;
}
Reset_Timer -= diff;
if (me->IsInCombat() && me->GetVictim())
{
if (Player* player = me->GetVictim()->ToPlayer())
{
if (player->GetTeamId() == TEAM_HORDE)
{
me->CombatStop();
me->GetThreatMgr().ClearAllThreat();
}
}
}
}
//Return since we have no target
if (!UpdateVictim())
return;
DoMeleeAttackIfReady();
}
};
};
/*######
##
######*/
void AddSC_stranglethorn_vale()
{
new npc_yenniku();
}
-38
View File
@@ -46,43 +46,6 @@ public:
}
};
struct npc_midsummer_bonfire : public ScriptedAI
{
npc_midsummer_bonfire(Creature* creature) : ScriptedAI(creature)
{
me->IsAIEnabled = true;
goGUID.Clear();
if (GameObject* go = me->SummonGameObject(GO_MIDSUMMER_BONFIRE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0))
{
goGUID = go->GetGUID();
me->RemoveGameObject(go, false);
}
}
ObjectGuid goGUID;
void SpellHit(Unit*, SpellInfo const* spellInfo) override
{
if (!goGUID)
return;
// Extinguish fire
if (spellInfo->Id == SPELL_STAMP_OUT_BONFIRE)
{
if (GameObject* go = ObjectAccessor::GetGameObject(*me, goGUID))
go->SetPhaseMask(2, true);
}
else if (spellInfo->Id == SPELL_LIGHT_BONFIRE)
{
if (GameObject* go = ObjectAccessor::GetGameObject(*me, goGUID))
{
go->SetPhaseMask(1, true);
go->SendCustomAnim(1);
}
}
}
};
struct npc_midsummer_torch_target : public ScriptedAI
{
npc_midsummer_torch_target(Creature* creature) : ScriptedAI(creature)
@@ -542,7 +505,6 @@ void AddSC_event_midsummer_scripts()
{
// NPCs
new go_midsummer_bonfire();
RegisterCreatureAI(npc_midsummer_bonfire);
RegisterCreatureAI(npc_midsummer_torch_target);
// Spells
@@ -66,231 +66,7 @@ public:
}
};
enum WanderingShay
{
QUEST_WANDERING_SHAY = 2845,
SPELL_SHAY_BELL = 11402,
NPC_ROCKBITER = 7765,
TALK_0 = 0,
TALK_1 = 1,
TALK_2 = 2,
TALK_3 = 3,
TALK_4 = 4,
EVENT_WANDERING_START = 1,
EVENT_WANDERING_TALK = 2,
EVENT_WANDERING_RANDOM = 3,
EVENT_FINAL_TALK = 4,
EVENT_CHECK_FOLLOWER = 5
};
class npc_shay_leafrunner : public CreatureScript
{
public:
npc_shay_leafrunner() : CreatureScript("npc_shay_leafrunner") {}
struct npc_shay_leafrunnerAI : public ScriptedAI
{
npc_shay_leafrunnerAI(Creature* creature) : ScriptedAI(creature) {}
void InitializeAI() override
{
me->SetNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
me->SetImmuneToAll(true);
me->RestoreFaction();
_events.Reset();
_playerGUID.Clear();
_rockbiterGUID.Clear();
}
void JustRespawned() override
{
InitializeAI();
me->SetHomePosition(me->GetPosition());
}
void MoveInLineOfSight(Unit* target) override
{
if (!_playerGUID || target->GetEntry() != NPC_ROCKBITER || !me->IsInRange(target, 0.f, 10.f))
{
if (!me->IsInCombat() && !me->GetVictim())
{
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
{
if (Unit* victim = player->GetVictim())
{
if (me->CanStartAttack(victim))
{
AttackStart(victim);
}
}
}
}
return;
}
_rockbiterGUID = target->GetGUID();
Talk(TALK_4, target);
me->SetControlled(true, UNIT_STATE_ROOT);
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
{
player->GroupEventHappens(QUEST_WANDERING_SHAY, me);
}
_events.CancelEvent(EVENT_WANDERING_START);
_events.ScheduleEvent(EVENT_FINAL_TALK, 5s);
}
void EnterEvadeMode(EvadeReason why) override
{
_EnterEvadeMode(why);
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
{
me->GetMotionMaster()->MoveFollow(player, 3.f, M_PI);
}
}
void FailQuest(Player* player, bool despawn)
{
if (player)
{
player->FailQuest(QUEST_WANDERING_SHAY);
if (Group* group = player->GetGroup())
{
for (GroupReference* groupRef = group->GetFirstMember(); groupRef != nullptr; groupRef = groupRef->next())
{
if (Player* member = groupRef->GetSource())
{
if (member->GetGUID() != player->GetGUID())
{
member->FailQuest(QUEST_WANDERING_SHAY);
}
}
}
}
}
if (despawn)
{
me->DespawnOrUnsummon(1);
}
}
void JustDied(Unit* /*killer*/) override
{
if (Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID))
{
FailQuest(player, false);
}
}
void sQuestAccept(Player* player, Quest const* quest) override
{
if (quest->GetQuestId() == QUEST_WANDERING_SHAY)
{
_playerGUID = player->GetGUID();
Talk(TALK_0, player);
me->RemoveNpcFlag(UNIT_NPC_FLAG_QUESTGIVER);
me->SetImmuneToAll(false);
me->SetFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
me->GetMotionMaster()->MoveFollow(player, 3.f, M_PI);
_events.ScheduleEvent(EVENT_WANDERING_START, 40s, 70s);
_events.ScheduleEvent(EVENT_CHECK_FOLLOWER, 30s);
}
}
void SpellHit(Unit* caster, SpellInfo const* spellInfo) override
{
if (spellInfo->Id == SPELL_SHAY_BELL)
{
_playerGUID = caster->GetGUID();
Talk(TALK_1, caster);
me->GetMotionMaster()->MoveIdle();
me->GetMotionMaster()->MoveFollow(caster, 3.f, M_PI);
}
}
void UpdateAI(uint32 diff) override
{
if (UpdateVictim())
{
DoMeleeAttackIfReady();
return;
}
_events.Update(diff);
while (uint32 eventId = _events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_WANDERING_START:
{
Position pos = me->GetFirstCollisionPosition(15.f, rand_norm() * static_cast<float>(2 * M_PI));
me->GetMotionMaster()->MovePoint(0, pos);
Talk(TALK_2);
_events.ScheduleEvent(EVENT_WANDERING_START, 60s, 70s);
_events.ScheduleEvent(EVENT_WANDERING_TALK, 3s);
_events.ScheduleEvent(EVENT_WANDERING_RANDOM, 8s);
break;
}
case EVENT_WANDERING_TALK:
Talk(TALK_3);
break;
case EVENT_WANDERING_RANDOM:
me->SetHomePosition(me->GetPosition());
me->GetMotionMaster()->MoveRandom(15.f);
break;
case EVENT_FINAL_TALK:
if (Creature* robckbiter = ObjectAccessor::GetCreature(*me, _rockbiterGUID))
{
robckbiter->AI()->Talk(TALK_0, me);
}
me->DespawnOrUnsummon(10 * IN_MILLISECONDS);
break;
case EVENT_CHECK_FOLLOWER:
{
Player* player = ObjectAccessor::GetPlayer(*me, _playerGUID);
if (!player || !player->IsAlive() || !me->IsInRange(player, 0.f, 50.f))
{
FailQuest(player, true);
}
break;
}
default:
break;
}
}
}
private:
ObjectGuid _playerGUID;
ObjectGuid _rockbiterGUID;
EventMap _events;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_shay_leafrunnerAI(creature);
}
};
void AddSC_feralas()
{
new spell_gordunni_trap();
new npc_shay_leafrunner();
}
@@ -97,9 +97,6 @@ public:
if (m_pInstance)
m_pInstance->SetData(TYPE_IONAR, NOT_STARTED);
// Ionar is immune to nature damage
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NATURE, true);
}
void ScheduleEvents(bool spark)
@@ -74,8 +74,11 @@ struct boss_exarch_maladaar : public BossAI
_Reset();
ScheduleHealthCheckEvent(25, [&] {
Talk(SAY_SUMMON);
scheduler.Schedule(100ms, [this](TaskContext)
{
DoCastSelf(SPELL_SUMMON_AVATAR);
});
});
}
void MoveInLineOfSight(Unit* who) override
@@ -133,6 +136,11 @@ struct boss_exarch_maladaar : public BossAI
_JustDied();
}
void JustSummoned(Creature* /*creature*/) override
{
// Override JustSummoned() so we don't despawn the Avatar.
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
@@ -208,25 +208,27 @@ class spell_murmur_thundering_storm : public SpellScript
}
};
// 33711/38794 - Murmur's Touch
class spell_murmur_touch : public AuraScript
// 33686 - Shockwave (Murmur's Touch final explosion)
class spell_shockwave_knockback : public SpellScript
{
PrepareAuraScript(spell_murmur_touch);
PrepareSpellScript(spell_shockwave_knockback);
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
bool Validate(SpellInfo const* /*spellInfo*/) override
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
{
if (GetTarget())
{
GetTarget()->CastSpell(GetTarget(), SPELL_SHOCKWAVE_SERVERSIDE, true);
return ValidateSpellInfo({ SPELL_SHOCKWAVE_SERVERSIDE });
}
void HandleOnHit()
{
if (Unit* target = GetHitUnit())
{
target->CastSpell(target, SPELL_SHOCKWAVE_SERVERSIDE, true);
}
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_murmur_touch::HandleAfterRemove, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
OnHit += SpellHitFn(spell_shockwave_knockback::HandleOnHit);
}
};
@@ -252,6 +254,6 @@ void AddSC_boss_murmur()
{
RegisterShadowLabyrinthCreatureAI(boss_murmur);
RegisterSpellScript(spell_murmur_thundering_storm);
RegisterSpellScript(spell_murmur_touch);
RegisterSpellScript(spell_shockwave_knockback);
RegisterSpellScript(spell_murmur_sonic_boom_effect);
}
@@ -55,6 +55,8 @@ enum EventSpells
SPELL_SUMMON_COLDWAVE = 45952,
SPELL_SUMMON_FROSTWIND = 45953,
SPELL_CHILLING_AURA = 46542,
/*
SPELL_SUMMON_ICE_SPEAR_BUNNY= 46359, // any dest
SPELL_ICE_SPEAR_KNOCKBACK = 46360, // src caster
@@ -63,6 +65,11 @@ enum EventSpells
*/
};
enum CreatureIds
{
NPC_AHUNITE_HAILSTONE = 25755
};
enum eEvents
{
EVENT_EMERGE = 1,
@@ -81,19 +88,14 @@ enum eEvents
EVENT_SPELL_SUMMON_COLDWAVE,
};
class boss_ahune : public CreatureScript
enum Misc
{
public:
boss_ahune() : CreatureScript("boss_ahune") { }
SET_GUID_INVOKER = 1
};
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetTheSlavePensAI<boss_ahuneAI>(pCreature);
}
struct boss_ahuneAI : public ScriptedAI
{
boss_ahuneAI(Creature* c) : ScriptedAI(c), summons(me)
struct boss_ahune : public ScriptedAI
{
boss_ahune(Creature* c) : ScriptedAI(c), summons(me)
{
SetCombatMovement(false);
SetEquipmentSlots(false, 54806, EQUIP_UNEQUIP, EQUIP_UNEQUIP);
@@ -109,17 +111,6 @@ public:
SummonList summons;
ObjectGuid InvokerGUID;
bool CanBeSeen(Player const* player) override
{
if (player->IsGameMaster())
{
return true;
}
Group const* group = player->GetGroup();
return group && sLFGMgr->GetDungeon(group->GetGUID()) == lfg::LFG_DUNGEON_FROST_LORD_AHUNE;
}
void StartPhase1()
{
me->CastSpell(me, SPELL_AHUNES_SHIELD, true);
@@ -136,6 +127,14 @@ public:
StartPhase1();
}
void SetGUID(ObjectGuid guid, int32 id) override
{
if (id == SET_GUID_INVOKER)
{
InvokerGUID = guid;
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim() && !me->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE))
@@ -146,7 +145,7 @@ public:
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
switch(events.ExecuteEvent())
switch (events.ExecuteEvent())
{
case 0:
break;
@@ -200,7 +199,7 @@ public:
me->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
me->CastSpell(me, SPELL_SUBMERGE_0, true);
me->CastSpell(me, SPELL_SELF_STUN, true);
if (Creature* c = DoSummon(NPC_FROZEN_CORE, *me, 24000, TEMPSUMMON_TIMED_DESPAWN))
if (Creature* c = DoSummon(NPC_FROZEN_CORE, *me, 24000, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN))
{
c->SetHealth(me->GetHealth());
}
@@ -217,6 +216,7 @@ public:
me->CastSpell(me, SPELL_EMERGE_0, false);
// me->CastSpell(me, SPELL_AHUNE_RESURFACES, true); // done in SummonedCreatureDespawn
me->RemoveAura(SPELL_SUBMERGE_0);
summons.DespawnEntry(NPC_FROZEN_CORE);
StartPhase1();
break;
@@ -236,8 +236,7 @@ public:
{
float dist = (float)urand(3, 10);
float angle = rand_norm() * 2 * M_PI;
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_HAILSTONE, false);
events.RepeatEvent(30000);
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_HAILSTONE, false);
}
break;
case EVENT_SPELL_SUMMON_COLDWAVE:
@@ -245,14 +244,14 @@ public:
{
float dist = (float)urand(3, 10);
float angle = rand_norm() * 2 * M_PI;
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_COLDWAVE, false);
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_COLDWAVE, false);
}
{
float dist = (float)urand(3, 10);
float angle = rand_norm() * 2 * M_PI;
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle)*dist, MinionSummonPos.GetPositionY() + std::sin(angle)*dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_FROSTWIND, false);
me->CastSpell(MinionSummonPos.GetPositionX() + cos(angle) * dist, MinionSummonPos.GetPositionY() + std::sin(angle) * dist, MinionSummonPos.GetPositionZ(), SPELL_SUMMON_FROSTWIND, false);
}
events.RepeatEvent(6000);
events.RepeatEvent(12000);
break;
default:
@@ -275,11 +274,18 @@ public:
}
void JustSummoned(Creature* summon) override
{
if (summon)
{
summons.Summon(summon);
summon->SetInCombatWithZone();
if (summon->GetEntry() == NPC_AHUNITE_HAILSTONE)
{
// Doesn't work when cast normally or when added to
// creature template addon. Needs further investigation.
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_CHILLING_AURA))
{
Aura::TryRefreshStackOrCreate(spellInfo, MAX_EFFECT_MASK, summon, summon);
}
}
}
@@ -305,10 +311,8 @@ public:
me->RemoveGameObject(chest, false);
bool finished = false;
Map::PlayerList const& players = me->GetMap()->GetPlayers();
if (!players.IsEmpty())
for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i)
if (Player* player = i->GetSource())
me->GetMap()->DoForAllPlayers([&](Player* player)
{
player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE, 25740, 1, me);
@@ -317,9 +321,8 @@ public:
finished = true;
sLFGMgr->FinishDungeon(player->GetGroup()->GetGUID(), lfg::LFG_DUNGEON_FROST_LORD_AHUNE, me->FindMap());
}
});
}
}
};
};
class go_ahune_ice_stone : public GameObjectScript
@@ -331,8 +334,18 @@ public:
{
if (!player || !go)
return true;
if (!player->HasItemCount(ITEM_MAGMA_TOTEM))
if (!player->IsGameMaster())
{
if (Group const* group = player->GetGroup())
{
if (sLFGMgr->GetDungeon(group->GetGUID()) != lfg::LFG_DUNGEON_FROST_LORD_AHUNE)
{
return true;
}
}
}
if (go->FindNearestCreature(NPC_AHUNE, 200.0f, true))
return true;
@@ -345,9 +358,19 @@ public:
{
if (!player || !go)
return true;
if (action != GOSSIP_ACTION_INFO_DEF + 1337)
if (!player->IsGameMaster())
{
if (Group const* group = player->GetGroup())
{
if (sLFGMgr->GetDungeon(group->GetGUID()) != lfg::LFG_DUNGEON_FROST_LORD_AHUNE)
{
return true;
if (!player->HasItemCount(ITEM_MAGMA_TOTEM))
}
}
}
if (action != GOSSIP_ACTION_INFO_DEF + 1337)
return true;
if (go->FindNearestCreature(NPC_AHUNE, 200.0f, true))
return true;
@@ -360,7 +383,11 @@ public:
c->SetVisible(false);
c->SetDisplayId(AHUNE_DEFAULT_MODEL);
c->SetFloatValue(UNIT_FIELD_COMBATREACH, 18.0f);
CAST_AI(boss_ahune::boss_ahuneAI, c->AI())->InvokerGUID = player->GetGUID();
if (c->AI())
{
c->AI()->SetGUID(player->GetGUID(), SET_GUID_INVOKER);
}
if (Creature* bunny = go->SummonCreature(NPC_AHUNE_SUMMON_LOC_BUNNY, AhuneSummonPos, TEMPSUMMON_TIMED_DESPAWN, 12000))
if (Creature* crystal_trigger = go->SummonCreature(WORLD_TRIGGER, go->GetPositionX(), go->GetPositionY(), 5.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 12000))
crystal_trigger->CastSpell(bunny, SPELL_STARTING_BEAM, false);
@@ -371,30 +398,8 @@ public:
}
};
class npc_ahune_frozen_core : public CreatureScript
{
public:
npc_ahune_frozen_core() : CreatureScript("npc_ahune_frozen_core") { }
CreatureAI* GetAI(Creature* pCreature) const override
{
return GetTheSlavePensAI<npc_ahune_frozen_coreAI>(pCreature);
}
struct npc_ahune_frozen_coreAI : public NullCreatureAI
{
npc_ahune_frozen_coreAI(Creature* c) : NullCreatureAI(c) {}
void JustDied(Unit* /*killer*/) override
{
me->DespawnOrUnsummon();
}
};
};
void AddSC_boss_ahune()
{
new go_ahune_ice_stone();
new boss_ahune();
new npc_ahune_frozen_core();
RegisterTheSlavePensCreatureAI(boss_ahune);
}
@@ -30,8 +30,6 @@ enum MekgineerSteamrigger
SPELL_SAW_BLADE = 31486,
SPELL_ELECTRIFIED_NET = 35107,
SPELL_ENRAGE = 26662,
SPELL_REPAIR_N = 31532,
SPELL_REPAIR_H = 37936,
SPELL_SUMMON_MECHANICS_1 = 31528,
SPELL_SUMMON_MECHANICS_2 = 31529,
@@ -85,7 +85,15 @@ struct boss_swamplord_muselek : public BossAI
bool CanShootVictim()
{
return me->GetVictim() && !me->IsWithinRange(me->GetVictim(), 10.0f) && me->IsWithinLOSInMap(me->GetVictim());
Unit* victim = me->GetVictim();
if (!victim || !me->IsWithinLOSInMap(victim) || !me->IsWithinRange(victim, 30.f) || me->IsWithinRange(victim, 10.f))
{
_canChase = true;
return false;
}
return true;
}
void JustEngagedWith(Unit* /*who*/) override
@@ -100,6 +108,8 @@ struct boss_swamplord_muselek : public BossAI
me->LoadEquipment(1, true);
DoCastVictim(SPELL_SHOOT);
me->GetMotionMaster()->Clear();
me->StopMoving();
_canChase = false;
}
else if (_canChase)
{
@@ -121,7 +131,7 @@ struct boss_swamplord_muselek : public BossAI
context.Repeat(20s, 30s);
}).Schedule(30s, 40s, [this](TaskContext context)
{
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 100.0f, false, true))
if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 40.0f, false, true))
{
_markTarget = target->GetGUID();
_canChase = false;
@@ -135,6 +145,7 @@ struct boss_swamplord_muselek : public BossAI
{
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MoveForwards(me->GetVictim(), 10.0f);
_canChase = false;
}
me->m_Events.AddEventAtOffset([this]()
@@ -17,6 +17,7 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "TaskScheduler.h"
#include "hellfire_ramparts.h"
enum Says
@@ -83,11 +84,6 @@ struct boss_vazruden_the_herald : public BossAI
}
}
void JustDied(Unit*) override
{
instance->SetBossState(DATA_VAZRUDEN, DONE);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_MIDDLE)
@@ -105,7 +101,7 @@ struct boss_vazruden_the_herald : public BossAI
{
Talk(SAY_INTRO);
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, -1406.5f, 1746.5f, 85.0f, false);
me->setActive(true);
_JustEngagedWith();
}
else if (summons.size() == 0)
{
@@ -139,11 +135,11 @@ struct boss_vazruden_the_herald : public BossAI
}
};
struct boss_nazan : public BossAI
struct boss_nazan : public ScriptedAI
{
boss_nazan(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
boss_nazan(Creature* creature) : ScriptedAI(creature)
{
scheduler.SetValidator([this]
_scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
@@ -162,11 +158,11 @@ struct boss_nazan : public BossAI
void JustEngagedWith(Unit*) override
{
scheduler.CancelGroup(GROUP_PHASE_2);
scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
_scheduler.CancelAll();
_scheduler.Schedule(5ms, GROUP_PHASE_1, [this](TaskContext context)
{
me->GetMotionMaster()->MovePoint(POINT_FLIGHT, NazanPos[urand(0, 2)], false);
scheduler.DelayAll(7s);
_scheduler.DelayAll(7s);
context.Repeat(30s);
}).Schedule(5s, GROUP_PHASE_1, [this](TaskContext context)
{
@@ -191,6 +187,7 @@ struct boss_nazan : public BossAI
{
if (param == ACTION_FLY_DOWN)
{
_scheduler.CancelGroup(GROUP_PHASE_1);
Talk(EMOTE_NAZAN);
me->SetReactState(REACT_PASSIVE);
me->InterruptNonMeleeSpells(true);
@@ -205,9 +202,8 @@ struct boss_nazan : public BossAI
me->SetCanFly(false);
me->SetDisableGravity(false);
me->SetReactState(REACT_AGGRESSIVE);
scheduler.CancelGroup(GROUP_PHASE_1);
me->GetMotionMaster()->MoveChase(me->GetVictim());
scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
_scheduler.Schedule(5s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastVictim(SPELL_CONE_OF_FIRE);
context.Repeat(12s);
@@ -216,9 +212,10 @@ struct boss_nazan : public BossAI
DoCastRandomTarget(SPELL_FIREBALL);
context.Repeat(4s, 6s);
});
if (IsHeroic())
{
scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
_scheduler.Schedule(10s, GROUP_PHASE_2, [this](TaskContext context)
{
DoCastSelf(SPELL_BELLOWING_ROAR);
context.Repeat(30s);
@@ -227,24 +224,28 @@ struct boss_nazan : public BossAI
}
}
void UpdateAI(uint32 /*diff*/) override
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (me->HasUnitState(UNIT_STATE_CASTING))
return;
_scheduler.Update(diff, [this]
{
if (!me->IsLevitating())
DoMeleeAttackIfReady();
});
}
private:
TaskScheduler _scheduler;
};
struct boss_vazruden : public BossAI
struct boss_vazruden : public ScriptedAI
{
boss_vazruden(Creature* creature) : BossAI(creature, DATA_VAZRUDEN)
boss_vazruden(Creature* creature) : ScriptedAI(creature)
{
scheduler.SetValidator([this]
_scheduler.SetValidator([this]
{
return !me->HasUnitState(UNIT_STATE_CASTING);
});
@@ -263,7 +264,7 @@ struct boss_vazruden : public BossAI
void JustEngagedWith(Unit*) override
{
scheduler.Schedule(5s, [this](TaskContext /*context*/)
_scheduler.Schedule(5s, [this](TaskContext /*context*/)
{
Talk(SAY_AGGRO);
}).Schedule(4s, [this](TaskContext context)
@@ -280,7 +281,7 @@ struct boss_vazruden : public BossAI
_hasSpoken = true;
Talk(SAY_KILL);
}
scheduler.Schedule(6s, [this](TaskContext /*context*/)
_scheduler.Schedule(6s, [this](TaskContext /*context*/)
{
_hasSpoken = false;
});
@@ -305,13 +306,16 @@ struct boss_vazruden : public BossAI
if (!UpdateVictim())
return;
scheduler.Update(diff);
_scheduler.Update(diff, [this]
{
DoMeleeAttackIfReady();
});
}
private:
bool _hasSpoken;
bool _nazanCalled;
TaskScheduler _scheduler;
};
class spell_vazruden_fireball : public SpellScript
@@ -144,17 +144,21 @@ class spell_capacitus_polarity_charge : public SpellScript
void HandleTargets(std::list<WorldObject*>& targetList)
{
uint8 count = 0;
for (std::list<WorldObject*>::iterator ihit = targetList.begin(); ihit != targetList.end(); ++ihit)
if ((*ihit)->GetGUID() != GetCaster()->GetGUID())
if (Player* target = (*ihit)->ToPlayer())
for (auto& ihit : targetList)
if (ihit->GetGUID() != GetCaster()->GetGUID())
if (Player* target = ihit->ToPlayer())
if (target->HasAura(GetTriggeringSpell()->Id))
++count;
uint32 spellId = GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE ? SPELL_POSITIVE_CHARGE_STACK : SPELL_NEGATIVE_CHARGE_STACK;
if (count)
{
uint32 spellId = GetSpellInfo()->Id == SPELL_POSITIVE_CHARGE ? SPELL_POSITIVE_CHARGE_STACK : SPELL_NEGATIVE_CHARGE_STACK;
GetCaster()->SetAuraStack(spellId, GetCaster(), count);
}
else
{
GetCaster()->RemoveAurasDueToSpell(spellId);
}
}
void HandleDamage(SpellEffIndex /*effIndex*/)
@@ -174,6 +178,29 @@ class spell_capacitus_polarity_charge : public SpellScript
}
};
class spell_capacitus_polarity_charge_aura : public AuraScript
{
PrepareAuraScript(spell_capacitus_polarity_charge_aura);
void HandleAfterRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
{
Unit* target = GetTarget();
if (!target)
return;
target->RemoveAurasDueToSpell(SPELL_POSITIVE_CHARGE_STACK);
target->RemoveAurasDueToSpell(SPELL_NEGATIVE_CHARGE_STACK);
}
}
void Register() override
{
AfterEffectRemove += AuraEffectRemoveFn(spell_capacitus_polarity_charge_aura::HandleAfterRemove, EFFECT_1, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
class spell_capacitus_polarity_shift : public SpellScript
{
PrepareSpellScript(spell_capacitus_polarity_shift);
@@ -194,5 +221,6 @@ void AddSC_boss_mechano_lord_capacitus()
{
RegisterMechanarCreatureAI(boss_mechano_lord_capacitus);
RegisterSpellScript(spell_capacitus_polarity_charge);
RegisterSpellScript(spell_capacitus_polarity_charge_aura);
RegisterSpellScript(spell_capacitus_polarity_shift);
}