diff --git a/contrib/grafana/1_General.json b/contrib/grafana/1_General.json new file mode 100644 index 0000000000..96b0c9170a --- /dev/null +++ b/contrib/grafana/1_General.json @@ -0,0 +1,889 @@ +{ + "id": 1, + "title": "General info", + "originalTitle": "General info", + "tags": [], + "style": "dark", + "timezone": "browser", + "editable": true, + "hideControls": false, + "sharedCrosshair": false, + "rows": [ + { + "collapse": false, + "editable": true, + "height": "25px", + "panels": [ + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": null, + "editable": true, + "error": false, + "format": "none", + "id": 5, + "interval": null, + "isNew": true, + "links": [], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "auto" + ], + "type": "time" + } + ], + "measurement": "online_players", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "type": "field", + "params": [ + "value" + ] + }, + { + "type": "last", + "params": [] + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=~", + "value": "/^$realm$/" + } + ] + } + ], + "thresholds": "", + "title": "Online players", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "current", + "timeFrom": null, + "timeShift": null, + "hideTimeOverride": false + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": null, + "editable": true, + "error": false, + "format": "none", + "id": 6, + "interval": null, + "isNew": true, + "links": [], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "auto" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "update_time_diff", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=~", + "value": "/^$realm$/" + } + ] + } + ], + "thresholds": "", + "title": "Update diff (avg)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg", + "timeFrom": "1m" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": null, + "editable": true, + "error": false, + "format": "none", + "id": 7, + "interval": null, + "isNew": true, + "links": [], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "auto" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "update_time_diff", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "thresholds": "", + "title": "Update diff (avg)", + "transparent": false, + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg", + "timeFrom": "5m" + }, + { + "cacheTimeout": null, + "colorBackground": false, + "colorValue": false, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": null, + "editable": true, + "error": false, + "format": "none", + "id": 8, + "interval": null, + "isNew": true, + "links": [], + "maxDataPoints": 100, + "nullPointMode": "connected", + "nullText": null, + "postfix": "", + "postfixFontSize": "50%", + "prefix": "", + "prefixFontSize": "50%", + "span": 3, + "sparkline": { + "fillColor": "rgba(31, 118, 189, 0.18)", + "full": false, + "lineColor": "rgb(31, 120, 193)", + "show": false + }, + "targets": [ + { + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "auto" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "update_time_diff", + "policy": "default", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=~", + "value": "/^$realm$/" + } + ] + } + ], + "thresholds": "", + "title": "Update diff (avg)", + "type": "singlestat", + "valueFontSize": "80%", + "valueMaps": [ + { + "op": "=", + "text": "N/A", + "value": "null" + } + ], + "valueName": "avg", + "timeFrom": "15m", + "timeShift": null + } + ], + "title": "New row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "Influx", + "editable": true, + "error": false, + "fill": 1, + "grid": { + "leftLogBase": 1, + "leftMax": null, + "leftMin": null, + "rightLogBase": 1, + "rightMax": null, + "rightMin": null, + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "id": 1, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Update diff", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "update_time_diff", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"update_time_diff\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(null)", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=~", + "value": "/$realm$/" + } + ] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Update diff", + "tooltip": { + "msResolution": false, + "shared": true, + "value_type": "cumulative" + }, + "type": "graph", + "x-axis": true, + "xaxis": { + "show": true + }, + "y-axis": true, + "y_formats": [ + "ms", + "short" + ], + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "Row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "Influx", + "editable": true, + "error": false, + "fill": 1, + "grid": { + "leftLogBase": 1, + "leftMax": null, + "leftMin": null, + "rightLogBase": 1, + "rightMax": null, + "rightMin": null, + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "id": 4, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Online players", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "online_players", + "policy": "default", + "query": "SELECT mean(\"value\") FROM \"online_players\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(null)", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=~", + "value": "/$realm$/" + } + ] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Online players", + "tooltip": { + "msResolution": false, + "shared": true, + "value_type": "cumulative" + }, + "type": "graph", + "x-axis": true, + "xaxis": { + "show": true + }, + "y-axis": true, + "y_formats": [ + "short", + "short" + ], + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "New row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "Influx", + "editable": true, + "error": false, + "fill": 1, + "grid": { + "leftLogBase": 1, + "leftMax": null, + "leftMin": null, + "rightLogBase": 1, + "rightMax": null, + "rightMin": null, + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "id": 3, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Logouts", + "transform": "negative-Y" + } + ], + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Logins", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "measurement": "player_events", + "policy": "default", + "query": "SELECT count(\"text\") FROM \"player_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'Login' AND $timeFilter GROUP BY time($interval) fill(0)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "text" + ], + "type": "field" + }, + { + "params": [], + "type": "count" + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=", + "value": "Trinity" + } + ] + }, + { + "alias": "Logouts", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "policy": "default", + "query": "SELECT count(\"text\") FROM \"player_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'Logout' AND $timeFilter GROUP BY time($interval) fill(0)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Player login/logout", + "tooltip": { + "msResolution": false, + "shared": true, + "value_type": "cumulative" + }, + "type": "graph", + "x-axis": true, + "xaxis": { + "show": true + }, + "y-axis": true, + "y_formats": [ + "short", + "short" + ], + "yaxes": [ + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + }, + { + "format": "short", + "label": null, + "logBase": 1, + "max": null, + "min": null, + "show": true + } + ] + } + ], + "title": "New row" + } + ], + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "templating": { + "list": [ + { + "allFormat": "regex values", + "current": { + "text": "Trinity", + "value": "Trinity" + }, + "datasource": null, + "includeAll": false, + "multi": false, + "multiFormat": "regex values", + "name": "realm", + "options": [ + { + "text": "Trinity", + "value": "Trinity", + "selected": true + } + ], + "query": "show tag values from events with key = realm", + "refresh": 1, + "regex": "", + "type": "query" + } + ] + }, + "annotations": { + "list": [ + { + "datasource": "Influx", + "enable": true, + "iconColor": "#C0C6BE", + "iconSize": 13, + "lineColor": "rgba(255, 96, 96, 0.592157)", + "name": "Global Events", + "query": "select title, text from events where $timeFilter and realm =~ /$realm$/", + "showLine": true, + "textColumn": "text", + "titleColumn": "title" + } + ] + }, + "refresh": "1m", + "schemaVersion": 12, + "version": 7, + "links": [] +} \ No newline at end of file diff --git a/contrib/grafana/2_Maps.json b/contrib/grafana/2_Maps.json new file mode 100644 index 0000000000..6c2cecb103 --- /dev/null +++ b/contrib/grafana/2_Maps.json @@ -0,0 +1,339 @@ +{ + "id": 2, + "title": "Maps, vmaps and mmaps", + "originalTitle": "Maps, vmaps and mmaps", + "tags": [], + "style": "dark", + "timezone": "browser", + "editable": true, + "hideControls": false, + "sharedCrosshair": false, + "rows": [ + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "Influx", + "editable": true, + "error": false, + "fill": 1, + "grid": { + "leftLogBase": 1, + "leftMax": null, + "leftMin": null, + "rightLogBase": 1, + "rightMax": null, + "rightMin": null, + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "id": 2, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [ + { + "alias": "Unload tile", + "transform": "negative-Y" + } + ], + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Load tile", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "0" + ], + "type": "fill" + } + ], + "query": "SELECT count(\"title\") FROM \"map_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'LoadMapTile' AND $timeFilter GROUP BY time($interval) fill(0)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + }, + { + "alias": "Unload tile", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "query": "SELECT count(\"title\") FROM \"map_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'UnloadMapTile' AND $timeFilter GROUP BY time($interval) fill(0)", + "rawQuery": true, + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Map", + "tooltip": { + "shared": true, + "value_type": "cumulative" + }, + "type": "graph", + "x-axis": true, + "y-axis": true, + "y_formats": [ + "short", + "short" + ] + } + ], + "title": "Row" + }, + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "Influx", + "editable": true, + "error": false, + "fill": 1, + "grid": { + "leftLogBase": 1, + "leftMax": null, + "leftMin": null, + "rightLogBase": 1, + "rightMax": null, + "rightMin": null, + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "id": 1, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Pathfinding queries", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "null" + ], + "type": "fill" + } + ], + "query": "SELECT count(\"title\") FROM \"mmap_events\" WHERE \"realm\" =~ /$realm$/ AND \"title\" = 'CalculatePath' AND $timeFilter GROUP BY time($interval) fill(0)", + "rawQuery": true, + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "MMap", + "tooltip": { + "shared": true, + "value_type": "cumulative" + }, + "type": "graph", + "x-axis": true, + "y-axis": true, + "y_formats": [ + "short", + "short" + ] + } + ], + "title": "New row" + } + ], + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "templating": { + "list": [ + { + "allFormat": "regex values", + "current": { + "text": "Trinity", + "value": "Trinity" + }, + "datasource": "Influx", + "includeAll": false, + "multi": false, + "multiFormat": "regex values", + "name": "realm", + "options": [ + { + "text": "Trinity", + "value": "Trinity", + "selected": true + } + ], + "query": "show tag values from events with key = realm", + "refresh": true, + "type": "query" + } + ] + }, + "annotations": { + "list": [ + { + "datasource": "Influx", + "enable": true, + "iconColor": "#C0C6BE", + "iconSize": 13, + "lineColor": "rgba(255, 96, 96, 0.592157)", + "name": "Global Events", + "query": "select title, text from events where $timeFilter and realm =~ /$realm$/", + "showLine": true, + "textColumn": "text", + "titleColumn": "title" + } + ] + }, + "refresh": "1m", + "schemaVersion": 8, + "version": 11, + "links": [] +} \ No newline at end of file diff --git a/contrib/grafana/3_Network.json b/contrib/grafana/3_Network.json new file mode 100644 index 0000000000..98c190e118 --- /dev/null +++ b/contrib/grafana/3_Network.json @@ -0,0 +1,242 @@ +{ + "id": 3, + "title": "Network", + "originalTitle": "Network", + "tags": [], + "style": "dark", + "timezone": "browser", + "editable": true, + "hideControls": false, + "sharedCrosshair": false, + "rows": [ + { + "collapse": false, + "editable": true, + "height": "250px", + "panels": [ + { + "aliasColors": {}, + "bars": false, + "datasource": "Influx", + "editable": true, + "error": false, + "fill": 1, + "grid": { + "leftLogBase": 1, + "leftMax": null, + "leftMin": null, + "rightLogBase": 1, + "rightMax": null, + "rightMin": null, + "threshold1": null, + "threshold1Color": "rgba(216, 200, 27, 0.27)", + "threshold2": null, + "threshold2Color": "rgba(234, 112, 112, 0.22)" + }, + "id": 1, + "isNew": true, + "legend": { + "avg": false, + "current": false, + "max": false, + "min": false, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "span": 12, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "Processed packets", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "0" + ], + "type": "fill" + } + ], + "measurement": "processed_packets", + "query": "SELECT sum(\"value\") FROM \"processed_packets\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(0)", + "refId": "A", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "sum" + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=~", + "value": "/$realm$/" + } + ] + }, + { + "alias": "Processed packets / mean per session", + "dsType": "influxdb", + "groupBy": [ + { + "params": [ + "$interval" + ], + "type": "time" + }, + { + "params": [ + "0" + ], + "type": "fill" + } + ], + "measurement": "processed_packets", + "query": "SELECT mean(\"value\") FROM \"processed_packets\" WHERE \"realm\" =~ /$realm$/ AND $timeFilter GROUP BY time($interval) fill(0)", + "refId": "B", + "resultFormat": "time_series", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "field" + }, + { + "params": [], + "type": "mean" + } + ] + ], + "tags": [ + { + "key": "realm", + "operator": "=~", + "value": "/$realm$/" + } + ] + } + ], + "timeFrom": null, + "timeShift": null, + "title": "Processed packets", + "tooltip": { + "shared": true, + "value_type": "cumulative" + }, + "type": "graph", + "x-axis": true, + "y-axis": true, + "y_formats": [ + "short", + "short" + ] + } + ], + "title": "Row" + } + ], + "time": { + "from": "now-15m", + "to": "now" + }, + "timepicker": { + "now": true, + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "templating": { + "list": [ + { + "allFormat": "regex values", + "current": { + "text": "Trinity", + "value": "Trinity" + }, + "datasource": "Influx", + "includeAll": false, + "multi": false, + "multiFormat": "regex values", + "name": "realm", + "options": [ + { + "text": "Trinity", + "value": "Trinity", + "selected": true + } + ], + "query": "show tag values from events with key = realm", + "refresh": true, + "type": "query" + } + ] + }, + "annotations": { + "list": [ + { + "datasource": "Influx", + "enable": true, + "iconColor": "#C0C6BE", + "iconSize": 13, + "lineColor": "rgba(255, 96, 96, 0.592157)", + "name": "Global Events", + "query": "select title, text from events where $timeFilter and realm =~ /$realm$/", + "showLine": true, + "textColumn": "text", + "titleColumn": "title" + } + ] + }, + "refresh": "1m", + "schemaVersion": 8, + "version": 7, + "links": [] +} \ No newline at end of file diff --git a/dep/efsw/CMakeLists.txt b/dep/efsw/CMakeLists.txt index eecc553194..f268558a52 100644 --- a/dep/efsw/CMakeLists.txt +++ b/dep/efsw/CMakeLists.txt @@ -1,5 +1,6 @@ if (BUILD_SHARED_LIBS) set(SRCS + src/efsw/Debug.cpp src/efsw/DirectorySnapshot.cpp src/efsw/DirectorySnapshotDiff.cpp src/efsw/DirWatcherGeneric.cpp diff --git a/sql/base/dev/world_database.sql b/sql/base/dev/world_database.sql index eba0c08a9e..9cffbbcbb3 100644 --- a/sql/base/dev/world_database.sql +++ b/sql/base/dev/world_database.sql @@ -657,20 +657,20 @@ DROP TABLE IF EXISTS `creature_text`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `creature_text` ( - `entry` mediumint(8) unsigned NOT NULL DEFAULT '0', - `groupid` tinyint(3) unsigned NOT NULL DEFAULT '0', - `id` tinyint(3) unsigned NOT NULL DEFAULT '0', - `text` longtext, - `type` tinyint(3) unsigned NOT NULL DEFAULT '0', - `language` tinyint(3) unsigned NOT NULL DEFAULT '0', - `probability` float NOT NULL DEFAULT '0', - `emote` mediumint(8) unsigned NOT NULL DEFAULT '0', - `duration` mediumint(8) unsigned NOT NULL DEFAULT '0', - `sound` mediumint(8) unsigned NOT NULL DEFAULT '0', + `CreatureID` mediumint(8) unsigned NOT NULL DEFAULT '0', + `GroupID` tinyint(3) unsigned NOT NULL DEFAULT '0', + `ID` tinyint(3) unsigned NOT NULL DEFAULT '0', + `Text` longtext, + `Type` tinyint(3) unsigned NOT NULL DEFAULT '0', + `Language` tinyint(3) unsigned NOT NULL DEFAULT '0', + `Probability` float NOT NULL DEFAULT '0', + `Emote` mediumint(8) unsigned NOT NULL DEFAULT '0', + `Duration` mediumint(8) unsigned NOT NULL DEFAULT '0', + `Sound` mediumint(8) unsigned NOT NULL DEFAULT '0', `BroadcastTextId` mediumint(6) NOT NULL DEFAULT '0', `TextRange` tinyint(3) unsigned NOT NULL DEFAULT '0', `comment` varchar(255) DEFAULT '', - PRIMARY KEY (`entry`,`groupid`,`id`) + PRIMARY KEY (`CreatureID`,`GroupID`,`ID`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; diff --git a/sql/updates/world/4.3.4/2017_05_22_00_world.sql b/sql/updates/world/4.3.4/2017_05_22_00_world.sql new file mode 100644 index 0000000000..895a91cf85 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_22_00_world.sql @@ -0,0 +1,128 @@ +-- Fixup Blackrock Worg +UPDATE `creature_template` SET `flags_extra`=2 WHERE `entry`=49871; + +-- Fix up Blackrock Spy Entry: 49874 +UPDATE `creature` SET `spawndist`=0,`MovementType`=0 WHERE `id`=49874; +UPDATE `creature_template_addon` SET `auras`='80676' WHERE `entry`=49874; +DELETE FROM `smart_scripts` WHERE `entryorguid`=49874 AND `id` IN (1,2); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279993; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-9017.051,`position_y`=-186.1771,`position_z`=76.99114 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9017.051,-186.1771,76.99114,0,0,0,0,100,0), +(@PATH,2,-9022.958,-180.9201,76.68597,0,0,0,0,100,0), +(@PATH,3,-9025.415,-177.9479,76.53362,0,0,0,0,100,0), +(@PATH,4,-9026.482,-173.7778,77.33782,0,0,0,0,100,0), +(@PATH,5,-9024.309,-167.1191,78.75359,0,0,0,0,100,0), +(@PATH,6,-9026.482,-173.7773,77.37859,0,0,0,0,100,0), +(@PATH,7,-9025.415,-177.9479,76.53362,0,0,0,0,100,0), +(@PATH,8,-9022.958,-180.9201,76.68597,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279970; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8975.587,`position_y`=-210.8681,`position_z`=74.38621 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8975.587,-210.8681,74.38621,0,0,0,0,100,0), +(@PATH,2,-8982.348,-208.6354,73.94993,0,0,0,0,100,0), +(@PATH,3,-8982.997,-201.5851,74.64426,0,0,0,0,100,0), +(@PATH,4,-8982.348,-208.6354,73.94993,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279996; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8959.651,`position_y`=-62.3316,`position_z`=92.46779 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8959.651,-62.3316,92.46779,0,0,0,0,100,0), +(@PATH,2,-8962.094,-58.05729,92.43849,0,0,0,0,100,0), +(@PATH,3,-8966.278,-58.07465,92.18849,0,0,0,0,100,0), +(@PATH,4,-8966.953,-59.75868,91.97262,0,0,0,0,100,0), +(@PATH,5,-8962.488,-59.94618,92.25246,0,0,0,0,100,0), +(@PATH,6,-8966.278,-58.07465,92.18849,0,0,0,0,100,0), +(@PATH,7,-8962.094,-58.05729,92.43849,0,0,0,0,100,0), +(@PATH,8,-8958.906,-60.77083,92.43849,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279821; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8937.439,`position_y`=-246.7691,`position_z`=79.06224 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8937.439,-246.7691,79.06224,0,0,0,0,100,0), +(@PATH,2,-8930.792,-241.4774,79.49934,0,0,0,0,100,0), +(@PATH,3,-8933.103,-246.651,78.92879,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279952; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8906.613,`position_y`=-39.17014,`position_z`=89.14458 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8906.613,-39.17014,89.14458,0,0,0,0,100,0), +(@PATH,2,-8900.656,-43.30903,86.97442,0,0,0,0,100,0), +(@PATH,3,-8906.398,-39.31641,89.20806,0,0,0,0,100,0), +(@PATH,4,-8911.556,-40.54688,89.57232,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279950; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8926.372,`position_y`=-68.80903,`position_z`=89.75582 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8926.372,-68.80903,89.75582,0,0,0,0,100,0), +(@PATH,2,-8929.808,-68.91666,89.97311,0,0,0,0,100,0), +(@PATH,3,-8922.819,-71.70834,89.15719,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279936; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8878.366,`position_y`=-92.23785,`position_z`=83.897 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8878.366,-92.23785,83.897,0,0,0,0,100,0), +(@PATH,2,-8873.397,-91.30903,83.17702,0,0,0,0,100,0), +(@PATH,3,-8870.214,-93.74132,82.54983,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279918; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8832.973,`position_y`=-120.3351,`position_z`=80.8506 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8832.973,-120.3351,80.8506,0,0,0,0,100,0), +(@PATH,2,-8831.473,-124.0399,80.79787,0,0,0,0,100,0), +(@PATH,3,-8837.326,-118.8611,80.59762,0,0,0,0,100,0); + +-- Pathing for Blackrock Spy Entry: 49874 'TDB FORMAT' +SET @NPC := 279756; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8784.361,`position_y`=-78.68403,`position_z`=89.64127 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '92857'); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8784.361,-78.68403,89.64127,0,0,0,0,100,0), +(@PATH,2,-8776.549,-79.15799,89.33903,0,0,0,0,100,0), +(@PATH,3,-8772.433,-83.78646,88.66227,0,0,0,0,100,0), +(@PATH,4,-8776.549,-79.15799,89.33903,0,0,0,0,100,0); diff --git a/sql/updates/world/4.3.4/2017_05_23_00_world.sql b/sql/updates/world/4.3.4/2017_05_23_00_world.sql new file mode 100644 index 0000000000..4232af239a --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_00_world.sql @@ -0,0 +1,141 @@ +DELETE FROM `quest_request_items` WHERE `ID` IN (28757,28762,28763,28764,28765,28766,28767,29078,28759,28769,28770,28771,28772,28773,28774,29079,28791,28792,28793,28794,28795,28796,28797,29081,28806,28808,28809,28810,28811,28812,28813,29082); +INSERT INTO `quest_request_items` (`ID`,`EmoteOnComplete`,`EmoteOnIncomplete`,`CompletionText`,`VerifiedBuild`) VALUES +(28757,6,0, 'Have you beaten back the Blackrock worgs?',0), +(28762,6,0, 'Have you beaten back the Blackrock worgs?',0), +(28763,6,0, 'Have you beaten back the Blackrock worgs?',0), +(28764,6,0, 'Have you beaten back the Blackrock worgs?',0), +(28765,6,0, 'Have you beaten back the Blackrock worgs?',0), +(28766,6,0, 'Have you beaten back the Blackrock worgs?',0), +(28767,6,0, 'Have you beaten back the Blackrock worgs?',0), +(29078,6,0, 'Have you beaten back the Blackrock worgs?',0), +(28759,5,0, 'Kill the spies!',0), +(28769,5,0, 'Kill the spies!',0), +(28770,5,0, 'Kill the spies!',0), +(28771,5,0, 'Kill the spies!',0), +(28772,5,0, 'Kill the spies!',0), +(28773,5,0, 'Kill the spies!',0), +(28774,5,0, 'Kill the spies!',0), +(29079,5,0, 'Kill the spies!',0), +(28791,0,0, 'Kill the goblin assassins',0), +(28792,0,0, 'Kill the goblin assassins',0), +(28793,0,0, 'Kill the goblin assassins',0), +(28794,0,0, 'Kill the goblin assassins',0), +(28795,0,0, 'Kill the goblin assassins',0), +(28796,0,0, 'Kill the goblin assassins',0), +(28797,0,0, 'Kill the goblin assassins',0), +(29081,0,0, 'Kill the goblin assassins',0), +(28806,5,0, 'Rescue our Soldiers!',0), +(28808,5,0, 'Rescue our Soldiers!',0), +(28809,5,0, 'Rescue our Soldiers!',0), +(28810,5,0, 'Rescue our Soldiers!',0), +(28811,5,0, 'Rescue our Soldiers!',0), +(28812,5,0, 'Rescue our Soldiers!',0), +(28813,5,0, 'Rescue our Soldiers!',0), +(29082,5,0, 'Rescue our Soldiers!',0); + +DELETE FROM `quest_offer_reward` WHERE `ID` IN (28757,28762,28763,28764,28765,28766,28767,29078,28759,28769,28770,28771,28772,28773,28774,29079,28780,28784,28785,28786,28787,28788,28789,29080,28806,28808,28809,28810,28811,28812,28813,29082,28791,28792,28793,28794,28795,28796,28797,29081,28817,28818,28819,28820,28821,28822,28823,29083); +INSERT INTO `quest_offer_reward` (`ID`,`Emote1`,`Emote2`,`Emote3`,`Emote4`,`EmoteDelay1`,`EmoteDelay2`,`EmoteDelay3`,`EmoteDelay4`,`RewardText`,`VerifiedBuild`) VALUES +(28757,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(28762,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(28763,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(28764,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(28765,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(28766,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(28767,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(29078,1,1,0,0,0,0,0,0, 'You''ve bought us a little time, $n, but we''ve got even bigger problems to deal with now.',0), +(28759,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(28769,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(28770,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(28771,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(28772,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(28773,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(28774,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(29079,21,1,5,0,0,0,0,0, 'Excellent work, $n. You''ve turned out to be quite an asset to this garrison. It''s time for you to train!',0), +(28780,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(28784,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(28785,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(28786,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(28787,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(28788,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(28789,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(29080,0,0,0,0,0,0,0,0, 'It''s true, we were ambushed. I don''t dare send any more soldiers out there and risk losing them too. I need a volunteer. Someone willing to risk their life!',0), +(28806,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(28808,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(28809,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(28810,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(28811,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(28812,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(28813,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(29082,273,4,0,0,0,0,0,0, 'I think you now understand the power of the Light. The Light giveth hope, $g brother:sister; and the Light taketh from the darkness! BLESSED BE THE LIGHT!',0), +(28791,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(28792,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(28793,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(28794,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(28795,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(28796,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(28797,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(29081,0,0,0,0,0,0,0,0, 'That will teach those monsters! They''ll think twice before taking another mercenary job for orcs.',0), +(28817,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0), +(28818,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0), +(28819,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0), +(28820,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0), +(28821,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0), +(28822,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0), +(28823,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0), +(29083,1,1,1,5,0,0,0,0, 'With your help we have managed to secure the northern and western sectors of Northshire. We still have a rather large contingency of Blackrock orcs to the east and they''ve begun burning down the forest!',0); + +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`NextQuestID`=28759 WHERE `ID`=28767; -- Hunter +UPDATE `quest_template_addon` SET `AllowableClasses`=128,`NextQuestID`=28769 WHERE `ID`=28757; -- Mage +UPDATE `quest_template_addon` SET `AllowableClasses`=2,`NextQuestID`=28770 WHERE `ID`=28762; -- Paladin +UPDATE `quest_template_addon` SET `AllowableClasses`=16,`NextQuestID`=28771 WHERE `ID`=28763; -- Priest +UPDATE `quest_template_addon` SET `AllowableClasses`=8,`NextQuestID`=28772 WHERE `ID`=28764; -- Rogue +UPDATE `quest_template_addon` SET `AllowableClasses`=256,`NextQuestID`=28773 WHERE `ID`=28765; -- Warlock +UPDATE `quest_template_addon` SET `AllowableClasses`=1,`NextQuestID`=28774 WHERE `ID`=28766; -- Warrior +UPDATE `quest_template_addon` SET `AllowableClasses`=32,`NextQuestID`=29079 WHERE `ID`=29078; -- Deathknight + +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`NextQuestID`=28780 WHERE `ID`=28759; -- Hunter +UPDATE `quest_template_addon` SET `AllowableClasses`=128,`NextQuestID`=28784 WHERE `ID`=28769; -- Mage +UPDATE `quest_template_addon` SET `AllowableClasses`=2,`NextQuestID`=28785 WHERE `ID`=28770; -- Paladin +UPDATE `quest_template_addon` SET `AllowableClasses`=16,`NextQuestID`=28786 WHERE `ID`=28771; -- Priest +UPDATE `quest_template_addon` SET `AllowableClasses`=8,`NextQuestID`=28787 WHERE `ID`=28772; -- Rogue +UPDATE `quest_template_addon` SET `AllowableClasses`=256,`NextQuestID`=28788 WHERE `ID`=28773; -- Warlock +UPDATE `quest_template_addon` SET `AllowableClasses`=1,`NextQuestID`=28789 WHERE `ID`=28774; -- Warrior +UPDATE `quest_template_addon` SET `AllowableClasses`=32,`NextQuestID`=29080 WHERE `ID`=29079; -- Deathknight + +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`NextQuestID`=28791 WHERE `ID`=28780; -- Hunter +UPDATE `quest_template_addon` SET `AllowableClasses`=128,`NextQuestID`=28792 WHERE `ID`=28784; -- Mage +UPDATE `quest_template_addon` SET `AllowableClasses`=2,`NextQuestID`=28793 WHERE `ID`=28785; -- Paladin +UPDATE `quest_template_addon` SET `AllowableClasses`=16,`NextQuestID`=28794 WHERE `ID`=28786; -- Priest +UPDATE `quest_template_addon` SET `AllowableClasses`=8,`NextQuestID`=28795 WHERE `ID`=28787; -- Rogue +UPDATE `quest_template_addon` SET `AllowableClasses`=256,`NextQuestID`=28796 WHERE `ID`=28788; -- Warlock +UPDATE `quest_template_addon` SET `AllowableClasses`=1,`NextQuestID`=28797 WHERE `ID`=28789; -- Warrior +UPDATE `quest_template_addon` SET `AllowableClasses`=32,`NextQuestID`=29081 WHERE `ID`=29080; -- Deathknight + +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`NextQuestID`=28817 WHERE `ID`=28791; -- Hunter +UPDATE `quest_template_addon` SET `AllowableClasses`=128,`NextQuestID`=28818 WHERE `ID`=28792; -- Mage +UPDATE `quest_template_addon` SET `AllowableClasses`=2,`NextQuestID`=28819 WHERE `ID`=28793; -- Paladin +UPDATE `quest_template_addon` SET `AllowableClasses`=16,`NextQuestID`=28820 WHERE `ID`=28794; -- Priest +UPDATE `quest_template_addon` SET `AllowableClasses`=8,`NextQuestID`=28821 WHERE `ID`=28795; -- Rogue +UPDATE `quest_template_addon` SET `AllowableClasses`=256,`NextQuestID`=28822 WHERE `ID`=28796; -- Warlock +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`NextQuestID`=28823 WHERE `ID`=28797; -- Warrior +UPDATE `quest_template_addon` SET `AllowableClasses`=32,`NextQuestID`=29083 WHERE `ID`=29081; -- Deathknight + +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`PrevQuestID`=28780 WHERE `ID`=28806; -- Hunter +UPDATE `quest_template_addon` SET `AllowableClasses`=128,`PrevQuestID`=28784 WHERE `ID`=28808; -- Mage +UPDATE `quest_template_addon` SET `AllowableClasses`=2,`PrevQuestID`=28785 WHERE `ID`=28809; -- Paladin +UPDATE `quest_template_addon` SET `AllowableClasses`=16,`PrevQuestID`=28786 WHERE `ID`=28810; -- Priest +UPDATE `quest_template_addon` SET `AllowableClasses`=8,`PrevQuestID`=28787 WHERE `ID`=28811; -- Rogue +UPDATE `quest_template_addon` SET `AllowableClasses`=256,`PrevQuestID`=28788 WHERE `ID`=28812; -- Warlock +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`PrevQuestID`=28789 WHERE `ID`=28813; -- Warrior +UPDATE `quest_template_addon` SET `AllowableClasses`=32,`PrevQuestID`=29080 WHERE `ID`=29082; -- Deathknight + +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`NextQuestID`=26389 WHERE `ID`=28817; -- Hunter +UPDATE `quest_template_addon` SET `AllowableClasses`=128,`NextQuestID`=26389 WHERE `ID`=28818; -- Mage +UPDATE `quest_template_addon` SET `AllowableClasses`=2,`NextQuestID`=26389 WHERE `ID`=28819; -- Paladin +UPDATE `quest_template_addon` SET `AllowableClasses`=16,`NextQuestID`=26389 WHERE `ID`=28820; -- Priest +UPDATE `quest_template_addon` SET `AllowableClasses`=8,`NextQuestID`=26389 WHERE `ID`=28821; -- Rogue +UPDATE `quest_template_addon` SET `AllowableClasses`=256,`NextQuestID`=26389 WHERE `ID`=28822; -- Warlock +UPDATE `quest_template_addon` SET `AllowableClasses`=4,`NextQuestID`=26389 WHERE `ID`=28823; -- Warrior +UPDATE `quest_template_addon` SET `AllowableClasses`=32,`NextQuestID`=26389 WHERE `ID`=29083; -- Deathknight + +UPDATE `creature_queststarter` SET `id`=197 WHERE `quest` IN (28780,28784,28785,28786,28787,28788,28789,29080); diff --git a/sql/updates/world/4.3.4/2017_05_23_01_world.sql b/sql/updates/world/4.3.4/2017_05_23_01_world.sql new file mode 100644 index 0000000000..94eb69aef0 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_01_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `AllowableClasses`=1 WHERE `ID`=28797; -- Warrior diff --git a/sql/updates/world/4.3.4/2017_05_23_02_world_from_335_was_2017_05_16_01_world.sql b/sql/updates/world/4.3.4/2017_05_23_02_world_from_335_was_2017_05_16_01_world.sql new file mode 100644 index 0000000000..745670aa04 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_02_world_from_335_was_2017_05_16_01_world.sql @@ -0,0 +1,264 @@ +/* + * Thorim + */ + +DELETE FROM `creature_text` WHERE `CreatureID` IN (32865,32872,32873,33196); +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextID`, `comment`) VALUES +-- Thorim +(32865, 0,0,'Interlopers! You mortals who dare to interfere with my sport will pay... Wait--you...',14,0,100,0,0,15733,33145,'Thorim SAY_AGGRO_1'), +(32865, 1,0,'I remember you... In the mountains... But you... what is this? Where am--',14,0,100,0,0,15734,33270,'Thorim SAY_AGGRO_2'), +(32865, 2,0,'Do not hold back! Destroy them!',14,0,100,0,0,15736,34241,'Thorim SAY_SPECIAL'), +(32865, 3,0,'Impertinent whelps, you dare challenge me atop my pedestal? I will crush you myself!',14,0,100,0,0,15738,33148,'Thorim SAY_JUMPDOWN'), +(32865, 4,0,'Can''t you at least put up a fight!?',14,0,100,0,0,15739,34239,'Thorim SAY_SLAY_1'), +(32865, 4,1,'Pathetic.',14,0,100,0,0,15740,35768,'Thorim SAY_SLAY_2'), +(32865, 5,0,'My patience has reached its limit!',14,0,100,0,0,15741,33365,'Thorim SAY_BERSERK'), +(32865, 6,0,'Failures! Weaklings!',14,0,100,0,0,15742,33274,'Thorim SAY_WIPE'), +(32865, 7,0,'Stay your arms! I yield!',14,0,100,0,0,15743,33948,'Thorim SAY_DEATH'), +(32865, 8,0,'I feel as though I am awakening from a nightmare, but the shadows in this place yet linger.',14,0,100,0,0,15744,33949,'Thorim SAY_END_NORMAL_1'), +(32865, 9,0,'Sif... was Sif here? Impossible--she died by my brother''s hand. A dark nightmare indeed....',14,0,100,0,0,15745,33950,'Thorim SAY_END_NORMAL_2'), +(32865,10,0,'I need time to reflect.... I will aid your cause if you should require it. I owe you at least that much. Farewell.',14,0,100,0,0,15746,33951,'Thorim SAY_END_NORMAL_3'), +(32865,11,0,'You! Fiend! You are not my beloved! Be gone!',14,0,100,0,0,15747,33952,'Thorim SAY_END_HARD_1'), +(32865,12,0,'Behold the hand behind all the evil that has befallen Ulduar, left my kingdom in ruins, corrupted my brother, and slain my wife.',14,0,100,0,0,15748,33953,'Thorim SAY_END_HARD_2'), +(32865,13,0,'And now it falls to you, champions, to avenge us all. The task before you is great, but I will lend you my aid as I am able. You must prevail.',14,0,100,0,0,15749,33954,'Thorim SAY_END_HARD_3'), +-- Runic Colossus +(32872, 0,0,'%s surrounds itself with a crackling Runic Barrier!',41,0,100,0,0,0,33267,'Runic Colossus'), +-- Ancient Rune Giant +(32873, 0,0,'%s fortifies nearby allies with runic might!',41,0,100,0,0,0,33523,'Ancient Rune Giant'), +-- Sif +(33196, 0,0,'Thorim, my lord! Why else would these invaders have come into your sanctum but to slay you? They must be stopped!',14,0,100,0,0,15668,33325,'Sif - Start'), +(33196, 1,0,'These pathetic mortals are harmless, beneath my station. Dispose of them!',14,0,100,0,0,15669,33368,'Sif - Despawn'), +(33196, 2,0,'Impossible! Lord Thorim, I will bring your foes a frigid death!',14,0,100,0,0,15670,33369,'Sif - Event'); + +-- Lever SAI +SET @ENTRY := 194264; +UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI' WHERE `entry`=@ENTRY; +UPDATE `gameobject_template_addon` SET `flags`=32 WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=1; +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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,1,0,0,70,0,100,0,2,0,0,0,9,0,0,0,0,0,0,14,34155,0,0,0,0,0,0,'Lever - On Gameobject State Changed - Activate Gameobject'); + +-- Thorim Trap Bunny SAI +SET @ENTRY := 33054; +UPDATE `creature_template` SET `AIName`='SmartAI', `flags_extra`=2 WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,10,0,100,0,0,12,17000,17000,11,62241,0,0,0,0,0,1,0,0,0,0,0,0,0,'Thorim Trap Bunny - Within 0-12 Range Out of Combat LoS - Cast Paralytic Field'); + +SET @ENTRY := 33725; +UPDATE `creature_template` SET `AIName`='SmartAI', `flags_extra`=2 WHERE `entry`=@ENTRY; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +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`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,10,0,100,0,0,12,17000,17000,11,63540,0,0,0,0,0,1,0,0,0,0,0,0,0,'Thorim Trap Bunny - Within 0-12 Range Out of Combat LoS - Cast Paralytic Field'); + +DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_thorim_blizzard_effect','spell_thorim_frostbolt_volley','spell_thorim_charge_orb','spell_thorim_runic_smash','spell_thorim_stormhammer','spell_thorim_lightning_charge','spell_thorim_stormhammer_sif','spell_thorim_stormhammer_boomerang','spell_thorim_activate_lightning_orb_periodic','spell_iron_ring_guard_impale','spell_thorim_arena_leap'); +INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES +(62576,'spell_thorim_blizzard_effect'), +(62602,'spell_thorim_blizzard_effect'), +(62580,'spell_thorim_frostbolt_volley'), +(62604,'spell_thorim_frostbolt_volley'), +(62016,'spell_thorim_charge_orb'), +(62057,'spell_thorim_runic_smash'), +(62058,'spell_thorim_runic_smash'), +(62042,'spell_thorim_stormhammer'), +(62466,'spell_thorim_lightning_charge'), +(64767,'spell_thorim_stormhammer_sif'), +(64909,'spell_thorim_stormhammer_boomerang'), +(62184,'spell_thorim_activate_lightning_orb_periodic'), +(62331,'spell_iron_ring_guard_impale'), +(62418,'spell_iron_ring_guard_impale'), +(61934,'spell_thorim_arena_leap'); + +DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=62042; +DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = -62320; +INSERT INTO `spell_linked_spell` (`spell_trigger`, `spell_effect`, `type`, `comment`) VALUES +(-62320, -62398, 0, 'Aura of Celerity - Remove Visual'); + +-- Add dummy effect to kill credit so it actually selects targets +UPDATE `spell_dbc` SET `SchoolMask`=0 WHERE `Id`=64980; +UPDATE `spelleffect_dbc` SET `EffectImplicitTargetA`=18, `EffectImplicitTargetB`=16, `EffectRadiusIndex`=28, `Effect`=3 WHERE `EffectSpellId`=64980; +-- Correct attributes (SPELL_ATTR0_HIDE_IN_COMBAT_LOG, SPELL_ATTR2_CAN_TARGET_DEAD, SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) +UPDATE `spell_dbc` SET `Attributes`=`Attributes`|256, `AttributesEx2`=`AttributesEx2`|1|4 WHERE `Id` IN (64980,64985); + +DELETE FROM `spelldifficulty_dbc` WHERE `id` IN (62131,62315,62316,62333,62334,62335,62327,62328,62321,62331,62332,62613,62583,62577,62597,62580); +INSERT INTO `spelldifficulty_dbc` (`id`, `spellid0`, `spellid1`) VALUES +(62131,62131,64390), -- Chain Lightning +(62315,62315,62415), -- Acid Breath +(62316,62316,62417), -- Sweep +(62333,62333,62441), -- Renew +(62334,62334,62442), -- Greater Heal +(62335,62335,62443), -- Holy Smite +(62327,62327,62445), -- Runic Lightning +(62328,62328,62446), -- Runic Mending +(62321,62321,62529), -- Runic Shield +(62331,62331,62418), -- Impale +(62332,62332,62420), -- Shield Smash +(62613,62613,62614), -- Charge +(62583,62583,62601), -- Frostbolt +(62577,62577,62603), -- Blizzard +(62597,62597,62605), -- Frost Nova +(62580,62580,62604); -- Frostbolt Volley + +UPDATE `creature_template` SET `ScriptName`='boss_thorim' WHERE `entry`=32865; +UPDATE `creature_template` SET `ScriptName`='npc_sif' WHERE `entry`=33196; +UPDATE `creature_template` SET `ScriptName`='npc_thorim_pre_phase' WHERE `entry` IN (32885,32883,32908,32907,32882,32886); +UPDATE `creature_template` SET `ScriptName`='npc_thorim_arena_phase' WHERE `entry` IN (32876,32904,32878,32877,32874,32875,33110); +UPDATE `creature_template` SET `ScriptName`='npc_runic_colossus' WHERE `entry`=32872; +UPDATE `creature_template` SET `ScriptName`='npc_ancient_rune_giant' WHERE `entry`=32873; +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x40000000 WHERE `entry` IN (32872, 32873, 33148, 33149); +UPDATE `creature_template` SET `difficulty_entry_1`=33150 WHERE `entry`=32908; -- Swapped Difficulty entry npcs +UPDATE `creature_template` SET `difficulty_entry_1`=33151 WHERE `entry`=32907; -- Caused swapped displayIDs in 25n +UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=128, `ScriptName`='' WHERE `entry` IN (33140,33141); +UPDATE `creature_template` SET `InhabitType`=4, `flags_extra`=128 WHERE `entry` IN (33378,32879); +UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry` IN (32892); +UPDATE `creature_template` SET `faction`=1692 WHERE `entry` IN (32885,32883,33152,33153,32908,33150,32907,33151); +UPDATE `creature_template` SET `faction`=1693 WHERE `entry` IN (32882,33154); +UPDATE `creature_template` SET `speed_walk`=2.5/2.5, `speed_run`=14.0/7.0, `BaseAttackTime`=1500, `RangeAttackTime`=1500, `flags_extra`=`flags_extra`|0x00000200 WHERE `entry` IN (32865,33147); + +SET @THORIM_BLIZZARD_BUNNY := 136515; +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (62577,62603,62016,62976,63238,64098,62466,62565,62942,64767,62560,61964,61934); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 62577, 0, 0, 31, 0, 3, 32892, @THORIM_BLIZZARD_BUNNY, 0, 0, 0, '', 'Spell Blizzard (effect 0) will hit the potential target of the spell if target is unit Thorim Event Bunny guid 136515.'), +(13, 1, 62603, 0, 0, 31, 0, 3, 32892, @THORIM_BLIZZARD_BUNNY, 0, 0, 0, '', 'Spell Blizzard (effect 0) will hit the potential target of the spell if target is unit Thorim Event Bunny guid 136515.'), +(13, 1, 62016, 0, 0, 31, 0, 3, 33378, 0, 0, 0, 0, '', 'Spell Charge Orb (effect 0) will hit the potential target of the spell if target is unit Thunder Orb.'), +(13, 1, 62976, 0, 0, 31, 0, 3, 33378, 0, 0, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is unit Thunder Orb.'), +(13, 1, 62976, 0, 0, 33, 0, 1, 0, 0, 1, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is not the same as condition target.'), +(13, 1, 63238, 0, 0, 31, 0, 3, 33378, 0, 0, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is unit Thunder Orb.'), +(13, 1, 63238, 0, 0, 33, 0, 1, 0, 0, 1, 0, 0, '', 'Spell Lightning Pillar (effect 0) will hit the potential target of the spell if target is not the same as condition target.'), +(13, 1, 64098, 0, 0, 31, 0, 3, 32865, 0, 0, 0, 0, '', 'Spell Lightning Bolt (effect 0) will hit the potential target of the spell if target is unit Thorim.'), +(13, 4, 62466, 0, 0, 31, 0, 3, 32780, 0, 0, 0, 0, '', 'Spell Lightning Charge (effect 2) will hit the potential target of the spell if target is unit Invisible Stalker (All Phases).'), +(13, 3, 62565, 0, 0, 31, 0, 3, 32865, 0, 0, 0, 0, '', 'Spell Touch of Dominion (effects 0 & 1) will hit the potential target of the spell if target is unit Thorim.'), +(13, 7, 62942, 0, 0, 31, 0, 3, 32874, 0, 0, 0, 0, '', 'Spell Runic Fortification (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Iron Ring Guard.'), +(13, 7, 62942, 0, 1, 31, 0, 3, 32875, 0, 0, 0, 0, '', 'Spell Runic Fortification (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Iron Honor Guard.'), +(13, 7, 62942, 0, 2, 31, 0, 3, 33110, 0, 0, 0, 0, '', 'Spell Runic Fortification (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Acolyte.'), +(13, 1, 64767, 0, 0, 31, 0, 3, 33196, 0, 0, 0, 0, '', 'Spell Stormhammer (effect 0) will hit the potential target of the spell if target is unit Sif.'), +(13, 7, 62560, 0, 0, 31, 0, 3, 32876, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Champion.'), +(13, 7, 62560, 0, 1, 31, 0, 3, 32877, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Warbringer.'), +(13, 7, 62560, 0, 2, 31, 0, 3, 32878, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Evoker.'), +(13, 7, 62560, 0, 3, 31, 0, 3, 32904, 0, 0, 0, 0, '', 'Spell Berserk (effect 0 & 1 & 2) will hit the potential target of the spell if target is unit Dark Rune Commoner.'), +(13, 1, 61964, 0, 0, 31, 0, 3, 32882, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Jormungar Behemoth.'), +(13, 1, 61964, 0, 1, 31, 0, 3, 32883, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Soldier.'), +(13, 1, 61964, 0, 2, 31, 0, 3, 32885, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Soldier.'), +(13, 1, 61964, 0, 3, 31, 0, 3, 32886, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Dark Rune Acolyte.'), +(13, 1, 61964, 0, 4, 31, 0, 3, 32907, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Captain.'), +(13, 1, 61964, 0, 5, 31, 0, 3, 32908, 0, 0, 0, 0, '', 'Spell Circle of Healing (effect 0) will hit the potential target of the spell if target is unit Captured Mercenary Captain.'), +(13, 1, 61934, 0, 0, 31, 0, 3, 32892, 0, 0, 0, 0, 'condition_thorim_arena_leap', 'Spell Leap (effect 0) will hit the potential target of the spell if target is unit Thorim Event Bunny.'), +(13, 1, 61934, 0, 0, 31, 0, 3, 32892, @THORIM_BLIZZARD_BUNNY, 1, 0, 0, '', 'Spell Leap (effect 0) will hit the potential target of the spell if target is not unit Thorim Event Bunny guid 136515.'); + +DELETE FROM `disables` WHERE `sourceType`=4 AND `entry` IN (10289,10314,10304,10313,10440,10457,10800,10801); +INSERT INTO `disables` (`sourceType`,`entry`,`flags`,`params_0`,`params_1`,`comment`) VALUES +(4,10800,0,0,0,'Siffed (10 player) - Duplicate'), +(4,10801,0,0,0,'Siffed (25 player) - Duplicate'); + +DELETE FROM `disables` WHERE `sourceType`=0 AND `entry` IN (62042,64767,45537); +INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES +(0, 62042, 64, '', '', 'Stormhammer - Ignore LOS'), +(0, 64767, 64, '', '', 'Stormhammer - Ignore LOS'), +(0, 45537, 64, '', '', 'Lightning Beam Channel - Ignore LOS'); + +DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (10289,10314,10305,10309,10440,10457,10287,10288,10311,10312); +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`,`ScriptName`) VALUES +(10289,12,0,0,''), -- Siffed (10 player) +(10314,12,1,0,''), -- Siffed (25 player) + +(10305,11,0,0,'achievement_dont_stand_in_the_lightning'), -- Don't Stand in the Lightning (10 player) +(10305,12,0,0,''), -- Don't Stand in the Lightning (10 player) +(10309,11,0,0,'achievement_dont_stand_in_the_lightning'), -- Don't Stand in the Lightning (25 player) +(10309,12,1,0,''), -- Don't Stand in the Lightning (25 player) + +(10440,11,0,0,'achievement_lose_your_illusion'), -- Lose Your Illusion (10 player) +(10440,12,0,0,''), -- Lose Your Illusion (10 player) +(10457,11,0,0,'achievement_lose_your_illusion'), -- Lose Your Illusion (25 player) +(10457,12,1,0,''), -- Lose Your Illusion (25 player) + +(10287,11,0,0,'achievement_i_ll_take_you_all_on'), -- I'll Take You All On (10 player) - Participate in slaying Runic Colossus +(10287,12,0,0,''), +(10288,11,0,0,'achievement_i_ll_take_you_all_on'), -- I'll Take You All On (10 player) - Participate in slaying Ancient Rune Giant +(10288,12,0,0,''), +(10311,11,0,0,'achievement_i_ll_take_you_all_on'), -- I'll Take You All On (25 player) - Participate in slaying Runic Colossus +(10311,12,1,0,''), +(10312,11,0,0,'achievement_i_ll_take_you_all_on'), -- I'll Take You All On (25 player) - Participate in slaying Ancient Rune Giant +(10312,12,1,0,''); + +DELETE FROM `creature` WHERE `id` IN (32882,32908,32907,32885,32883,32886); -- PreAdds +DELETE FROM `creature` WHERE `id` IN (32874,32875,33110); -- Colossus, Giant Adds + +-- Fix Thorim Controller multi spawns +SET @CGUID:=136446; +DELETE FROM `creature` WHERE `id`=32879; +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `MovementType`) VALUES +(@CGUID, 32879, 603, 3, 1, 2134.774, -262.3073, 428.6936, 1.343904, 7200, 0, 0); -- 32879 (Area: 0) (Auras: 62184 - 62184) + +UPDATE `gameobject_template` SET `size`=3 WHERE `entry`=194315; +UPDATE `gameobject_template_addon` SET `faction`=94, `flags`=16 WHERE `entry` IN (194313,194314,194315); + +SET @OGUID := 3926; -- 4 free guids +DELETE FROM `gameobject` WHERE `id` IN (194312,194313,194314,194315); +INSERT INTO `gameobject` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) values +(@OGUID+0,194312,603,1,1,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-2592000,255,1,0), +(@OGUID+1,194313,603,1,1,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-2592000,255,1,0), +(@OGUID+2,194314,603,2,1,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-2592000,255,1,0), +(@OGUID+3,194315,603,2,1,2134.948,-286.436,419.5051,1.588249,0,0,0.7132502,0.7009096,-2592000,255,1,0); + +UPDATE `gameobject_loot_template` SET `LootMode`=1 WHERE `Entry`=27074; +DELETE FROM `gameobject_loot_template` WHERE `Entry` IN (26955,26956); +INSERT INTO `gameobject_loot_template` (`Entry`,`Item`,`Reference`,`Chance`,`QuestRequired`,`LootMode`,`GroupId`,`MinCount`,`MaxCount`,`Comment`) VALUES +(26955,1,34372,100,0,1,0,1,1,'Thorim25 HM - normal mode loot'), +(26955,2,12033,100,0,1,0,1,2,'Thorim25 HM - T8.5 tokens'), +(26955,3,34154,10,0,1,0,1,1,'Thorim25 HM - Random Ulduar craft recipe'), +(26955,45038,0,18,0,1,0,1,1,'Thorim25 HM - Val''anyr fragment'), +(26955,45087,0,10,0,1,0,1,1,'Thorim25 HM - Runed Orb'), +(26955,45470,0,0,0,1,1,1,1,'Thorim25 HM - Wisdom''s Hold'), +(26955,45471,0,0,0,1,1,1,1,'Thorim25 HM - Fate''s Clutch'), +(26955,45472,0,0,0,1,1,1,1,'Thorim25 HM - Warhelm of the Champion'), +(26955,45473,0,0,0,1,1,1,1,'Thorim25 HM - Embrace of the Gladiator'), +(26955,45474,0,0,0,1,1,1,1,'Thorim25 HM - Pauldrons of the Combatant'), +(26955,45570,0,0,0,1,1,1,1,'Thorim25 HM - Skyforge Crossbow'), +(26955,45817,0,100,1,1,0,1,1,'Thorim25 HM - Thorim''s Sigil'), +(26955,47241,0,100,0,1,0,1,1,'Thorim25 HM - Emblem of Triumph'), + +(26956,1,34372,100,0,1,0,1,1,'Thorim25 - normal mode loot'), +(26956,2,12033,100,0,1,0,1,2,'Thorim25 - T8.5 tokens'), +(26956,3,34154,10,0,1,0,1,1,'Thorim25 - Random Ulduar craft recipe'), +(26956,45038,0,8,0,1,0,1,1,'Thorim25 - Val''anyr fragment'), +(26956,45087,0,10,0,1,0,1,1,'Thorim25 - Runed Orb'), +(26956,47241,0,100,0,1,0,1,1,'Thorim25 - Emblem of Triumph'); + +-- Pathing for Thorim Event Bunny Entry: 32892 'TDB FORMAT' +SET @PATH := @THORIM_BLIZZARD_BUNNY * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=2148.425,`position_y`=-276.7478,`position_z`=419.5923 WHERE `guid`=@THORIM_BLIZZARD_BUNNY; +DELETE FROM `creature_addon` WHERE `guid`=@THORIM_BLIZZARD_BUNNY; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@THORIM_BLIZZARD_BUNNY,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,2148.425,-276.7478,419.5923,0,0,0,0,100,0), +(@PATH,2,2145.229,-278.5732,419.6016,0,0,0,0,100,0), +(@PATH,3,2142.105,-280.7194,419.5932,0,0,0,0,100,0), +(@PATH,4,2138.419,-281.2838,419.5999,0,0,0,0,100,0), +(@PATH,5,2134.843,-281.9885,419.5996,0,0,0,0,100,0), +(@PATH,6,2131.128,-281.278,419.5985,0,0,0,0,100,0), +(@PATH,7,2127.415,-280.8166,419.5875,0,0,0,0,100,0), +(@PATH,8,2124.459,-278.4777,419.6088,0,0,0,0,100,0), +(@PATH,9,2121.098,-276.7148,419.5924,0,0,0,0,100,0), +(@PATH,10,2119.281,-273.4217,419.6069,0,0,0,0,100,0), +(@PATH,11,2116.933,-270.4605,419.5851,0,0,0,0,100,0), +(@PATH,12,2116.359,-266.7142,419.6042,0,0,0,0,100,0), +(@PATH,13,2115.436,-263.0562,419.5847,0,0,0,0,100,0), +(@PATH,14,2116.543,-259.411,419.6082,0,0,0,0,100,0), +(@PATH,15,2116.943,-255.605,419.5851,0,0,0,0,100,0), +(@PATH,16,2119.377,-252.7493,419.6096,0,0,0,0,100,0), +(@PATH,17,2121.183,-249.3546,419.5858,0,0,0,0,100,0), +(@PATH,18,2124.49,-247.5925,419.6089,0,0,0,0,100,0), +(@PATH,19,2127.329,-245.1714,419.5925,0,0,0,0,100,0), +(@PATH,20,2131.097,-244.8609,419.6089,0,0,0,0,100,0), +(@PATH,21,2134.792,-243.7036,419.585,0,0,0,0,100,0), +(@PATH,22,2138.466,-244.3162,419.5979,0,0,0,0,100,0), +(@PATH,23,2142.386,-244.7266,419.5746,0,0,0,0,100,0), +(@PATH,24,2145.455,-247.1502,419.5968,0,0,0,0,100,0), +(@PATH,25,2148.564,-249.0781,419.5791,0,0,0,0,100,0), +(@PATH,26,2150.63,-252.4069,419.598,0,0,0,0,100,0), +(@PATH,27,2153.104,-255.5907,419.5758,0,0,0,0,100,0), +(@PATH,28,2153.286,-259.4698,419.6053,0,0,0,0,100,0), +(@PATH,29,2154.193,-263.0425,419.6039,0,0,0,0,100,0), +(@PATH,30,2153.279,-266.768,419.6026,0,0,0,0,100,0), +(@PATH,31,2152.758,-270.5462,419.5822,0,0,0,0,100,0), +(@PATH,32,2150.38,-273.4614,419.605,0,0,0,0,100,0); diff --git a/sql/updates/world/4.3.4/2017_05_23_03_world_from_335_was_2017_05_17_00_world.sql b/sql/updates/world/4.3.4/2017_05_23_03_world_from_335_was_2017_05_17_00_world.sql new file mode 100644 index 0000000000..3b946f6006 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_03_world_from_335_was_2017_05_17_00_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `creature_addon` WHERE `guid` IN (136274,136490,136555); diff --git a/sql/updates/world/4.3.4/2017_05_23_04_world_from_335_was_2017_05_22_00_world.sql b/sql/updates/world/4.3.4/2017_05_23_04_world_from_335_was_2017_05_22_00_world.sql new file mode 100644 index 0000000000..77fda7e8f0 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_04_world_from_335_was_2017_05_22_00_world.sql @@ -0,0 +1,25 @@ +-- +DELETE FROM `creature` WHERE `guid` IN (79380,79383,79609,79614,79626,79631,79636,79650,79876,79895,79899,79921,80289,80295,80299,80300,80303,80311,80312,80315,80316,80323); +INSERT INTO `creature` (`guid`, `id`, `map`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `curhealth`, `curmana`, `MovementType`) VALUES +(79380, 28603, 571, 1, 1, 0, 0, 6022.67, -2049.14, 238.189, 1.46482, 600, 10, 0, 0, 1), +(79383, 28603, 571, 1, 1, 0, 0, 6042.88, -2119.83, 239.522, 5.55282, 600, 10, 0, 0, 1), +(79609, 28603, 571, 1, 1, 0, 0, 6101.08, -2157.18, 239.578, 5.52926, 600, 10, 0, 0, 1), +(79614, 28603, 571, 1, 1, 0, 0, 6176.72, -2208.48, 241.65, 0.110007, 600, 10, 0, 0, 1), +(79626, 28603, 571, 1, 1, 0, 0, 6227.74, -2193.69, 236.211, 0.663713, 600, 10, 0, 0, 1), +(79631, 28603, 571, 1, 1, 0, 0, 6270.34, -2053.92, 238.548, 1.23705, 600, 10, 0, 0, 1), +(79636, 28603, 571, 1, 1, 0, 0, 6069.51, -1913.87, 236.212, 2.78429, 600, 10, 0, 0, 1), +(79650, 28603, 571, 1, 1, 0, 0, 6017.94, -1903.71, 239.384, 3.56183, 600, 10, 0, 0, 1), +(79876, 28603, 571, 1, 1, 0, 0, 5981.49, -1963.15, 237.669, 4.15088, 600, 10, 0, 0, 1), +(79895, 28603, 571, 1, 1, 0, 0, 6017.39, -2106.46, 243.382, 5.40752, 600, 10, 0, 0, 1), +(79899, 28603, 571, 1, 1, 0, 0, 5275.12, -1678.04, 236.349, 1.1703, 600, 10, 0, 0, 1), +(79921, 28603, 571, 1, 1, 0, 0, 5224.69, -1751.98, 235.717, 3.17306, 600, 10, 0, 0, 1), +(80289, 28603, 571, 1, 1, 0, 0, 5154.48, -1745.88, 238.291, 3.26731, 600, 10, 0, 0, 1), +(80295, 28603, 571, 1, 1, 0, 0, 5082.87, -1725.64, 235.624, 3.55791, 600, 10, 0, 0, 1), +(80299, 28603, 571, 1, 1, 0, 0, 5034.49, -1655.17, 240.16, 1.8693, 600, 10, 0, 0, 1), +(80300, 28603, 571, 1, 1, 0, 0, 5069.11, -1540.09, 240.561, 6.1183, 600, 10, 0, 0, 1), +(80303, 28603, 571, 1, 1, 0, 0, 5099.29, -1559.64, 238.941, 0.624444, 600, 10, 0, 0, 1), +(80311, 28603, 571, 1, 1, 0, 0, 6183.62, -2102.73, 235.653, 3.426750, 600, 10, 0, 0, 1), +(80312, 28603, 571, 1, 1, 0, 0, 6113.59, -2105.41, 234.909, 0.441447, 600, 10, 0, 0, 1), +(80315, 28603, 571, 1, 1, 0, 0, 6091.98, -2019.44, 235.639, 1.670596, 600, 10, 0, 0, 1), +(80316, 28603, 571, 1, 1, 0, 0, 6199.66, -1957.45, 234.049, 1.207211, 600, 10, 0, 0, 1), +(80323, 28603, 571, 1, 1, 0, 0, 6242.41, -2003.27, 234.282, 4.150887, 600, 10, 0, 0, 1); diff --git a/sql/updates/world/4.3.4/2017_05_23_05_world.sql b/sql/updates/world/4.3.4/2017_05_23_05_world.sql new file mode 100644 index 0000000000..2d0d7a6805 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_05_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `AllowableClasses`=1 WHERE `ID` IN (28823,29082); -- Warrior diff --git a/sql/updates/world/4.3.4/2017_05_23_06_world.sql b/sql/updates/world/4.3.4/2017_05_23_06_world.sql new file mode 100644 index 0000000000..7277f89765 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_06_world.sql @@ -0,0 +1,2 @@ +-- Delete no longer used 4.3.4 achievements for thorim +DELETE FROM achievement_criteria_data WHERE `type`=12; diff --git a/sql/updates/world/4.3.4/2017_05_23_07_world.sql b/sql/updates/world/4.3.4/2017_05_23_07_world.sql new file mode 100644 index 0000000000..e7a6977f90 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_07_world.sql @@ -0,0 +1,66 @@ +-- +SET @NPC := 322219; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=1395.607,`position_y`=1967.916,`position_z`=18.21449 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,1395.607,1967.916,18.21449,0,0,0,0,100,0), +(@PATH,2,1394.16,1971.855,18.46909,0,0,0,0,100,0), +(@PATH,3,1384.627,1984.173,18.75889,0,0,0,0,100,0), +(@PATH,4,1378.888,1992.172,18.40506,0,0,0,0,100,0), +(@PATH,5,1368.135,1992.527,17.40968,0,0,0,0,100,0), +(@PATH,6,1376.495,1993.365,18.46769,0,0,0,0,100,0), +(@PATH,7,1381.746,1987.858,18.92303,0,0,0,0,100,0), +(@PATH,8,1391.86,1975.847,18.5155,0,0,0,0,100,0); + +SET @NPC := 322231; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=1391.356,`position_y`=2009.19,`position_z`=15.90081 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,1391.356,2009.19,15.90081,0,0,0,0,100,0), +(@PATH,2,1396.165,2010.43,15.85461,0,0,0,0,100,0), +(@PATH,3,1411.213,2008.864,14.35008,0,0,0,0,100,0), +(@PATH,4,1422.343,2006.244,12.90728,0,0,0,0,100,0), +(@PATH,5,1434.081,2000.935,11.78559,0,0,0,0,100,0), +(@PATH,6,1448.412,1987.407,11.08783,0,0,0,0,100,0), +(@PATH,7,1444.67,1979.197,12.00837,0,0,0,0,100,0), +(@PATH,8,1448.225,1985.995,11.50098,0,0,0,0,100,0), +(@PATH,9,1440.929,1996.727,11.48743,0,0,0,0,100,0), +(@PATH,10,1425.209,2004.932,12.75235,0,0,0,0,100,0), +(@PATH,11,1412.675,2008.376,13.90751,0,0,0,0,100,0), +(@PATH,12,1403.565,2011.907,15.41258,0,0,0,0,100,0); + +SET @NPC := 322230; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=1411.675,`position_y`=1959.445,`position_z`=15.54728 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,1411.675,1959.445,15.54728,0,0,0,0,100,0), +(@PATH,2,1408.175,1957.945,16.29728,0,0,0,0,100,0); + +SET @NPC := 322213; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=1292.105,`position_y`=1954.99,`position_z`=19.55139 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,1292.105,1954.99,19.55139,0,0,0,0,100,0), +(@PATH,2,1312.855,1964.24,15.80139,0,0,0,0,100,0); + +UPDATE `creature_template_addon` SET `bytes2`=1, `auras`='71764' WHERE `entry`=1766; -- 1766 (Rabid Worg) +UPDATE `creature_template_addon` SET `bytes2`=1 WHERE `entry`=1797; -- 1797 (Giant Rabid Bear) +UPDATE `creature_template_addon` SET `auras`='83859' WHERE `entry`=44923; -- 44923 (North Tide's Invisible Stalker (Large)) +UPDATE `creature_template_addon` SET `auras`='' WHERE `entry`=1412; -- 1412 (Squirrel) +UPDATE `creature_template_addon` SET `bytes2`=1, `auras`='13886' WHERE `entry`=1780; -- 1780 (Skitterweb Striker) +UPDATE `creature_template_addon` SET `bytes2`=1 WHERE `entry`=1781; -- 1781 (Skitterweb Lurker) + +UPDATE `creature_template` SET `maxlevel`=11, `speed_run`=1 WHERE `entry`=1797; -- Giant Rabid Bear +UPDATE `creature_template` SET `npcflag`=0 WHERE `entry`=44906; -- Skitterweb Matriarch diff --git a/sql/updates/world/4.3.4/2017_05_23_08_world.sql b/sql/updates/world/4.3.4/2017_05_23_08_world.sql new file mode 100644 index 0000000000..f104b0a0f3 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_08_world.sql @@ -0,0 +1,33 @@ +-- +-- Pathing for Krethis the Shadowspinner Entry: 12433 'TDB FORMAT' +SET @NPC := 322085; +SET @PATH := @NPC * 10; + +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=1274.974,`position_y`=1897.126,`position_z`=21.38938 WHERE `guid`=@NPC; + +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); + +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,1274.974,1897.126,21.38938,0,0,0,0,100,0), -- 21:39:04 +(@PATH,2,1278.909,1908.219,23.45893,0,0,0,0,100,0), -- 21:39:09 +(@PATH,3,1284.339,1918.863,23.57857,0,0,0,0,100,0), -- 21:39:14 +(@PATH,4,1280.469,1924.43,20.27084,0,0,0,0,100,0), -- 21:39:18 +(@PATH,5,1271.227,1938.581,15.20391,0,0,0,0,100,0), -- 21:39:25 +(@PATH,6,1265.389,1958.833,14.73023,0,0,0,0,100,0), -- 21:39:33 +(@PATH,7,1255.614,1974.375,14.68589,0,0,0,0,100,0), -- 21:42:41 +(@PATH,8,1242.331,1979.81,12.17621,0,0,0,0,100,0), -- 21:42:47 +(@PATH,9,1221.198,1970.09,10.64629,0,0,0,0,100,0), -- 21:42:57 +(@PATH,10,1206.895,1964.751,10.06111,0,0,0,0,100,0), -- 21:43:03 +(@PATH,11,1186.084,1964.823,10.14644,0,0,0,0,100,0), -- 21:43:11 +(@PATH,12,1168.252,1950.556,9.711398,0,0,0,0,100,0), -- 21:43:21 +(@PATH,13,1167.201,1930.388,9.925863,0,0,0,0,100,0), -- 21:43:30 +(@PATH,14,1173.539,1917.193,12.24881,0,0,0,0,100,0), -- 21:43:36 +(@PATH,15,1183.568,1895.232,14.90211,0,0,0,0,100,0), -- 21:43:46 +(@PATH,16,1192.336,1879.673,16.86435,0,0,0,0,100,0), -- 21:43:53 +(@PATH,17,1211.627,1866.091,15.35263,0,0,0,0,100,0), -- 21:44:03 +(@PATH,18,1238.959,1854.467,9.821017,0,0,0,0,100,0), -- 21:44:15 +(@PATH,19,1248.241,1836.601,10.78487,0,0,0,0,100,0), -- 21:44:23 +(@PATH,20,1274.907,1834.172,18.62721,0,0,0,0,100,0), -- 21:44:36 +(@PATH,21,1273.366,1866.705,20.1383,0,0,0,0,100,0); -- 21:44:50 diff --git a/sql/updates/world/4.3.4/2017_05_23_09_world.sql b/sql/updates/world/4.3.4/2017_05_23_09_world.sql new file mode 100644 index 0000000000..da177c2fc8 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_23_09_world.sql @@ -0,0 +1,111 @@ +-- Pathing for Ix'lar the Underlord Entry: 45744 'TDB FORMAT' +SET @NPC := 319950; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=2845.473,`position_y`=-4767.625,`position_z`=84.60523 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,2845.473,-4767.625,84.60523,0,0,0,0,100,0), +(@PATH,2,2854.41,-4778.39,91.96474,0,0,0,0,100,0), +(@PATH,3,2862.23,-4789.15,95.09084,0,0,0,0,100,0), +(@PATH,4,2856.74,-4803.69,94.67984,0,0,0,0,100,0), +(@PATH,5,2842.84,-4805.25,97.01968,0,0,0,0,100,0), +(@PATH,6,2833.87,-4790.56,96.84133,0,0,0,0,100,0), +(@PATH,7,2825.65,-4788.4,99.6292,0,0,0,0,100,0), +(@PATH,8,2812.69,-4791.82,95.80302,0,0,0,0,100,0), +(@PATH,9,2805.72,-4798.94,90.90422,0,0,0,0,100,0), +(@PATH,10,2795.53,-4802.25,85.21287,0,0,0,0,100,0), +(@PATH,11,2783.56,-4801.21,83.14036,0,0,0,0,100,0), +(@PATH,12,2768.65,-4800.15,79.33762,0,0,0,0,100,0), +(@PATH,13,2755.91,-4794.9,76.57204,0,0,0,0,100,0), +(@PATH,14,2747,-4777.48,76.48952,0,0,0,0,100,0), +(@PATH,15,2748.14,-4746.14,76.97128,0,0,0,0,100,0), +(@PATH,16,2747.03,-4722.73,74.83576,0,0,0,0,100,0), +(@PATH,17,2750.93,-4698.12,78.95863,0,0,0,0,100,0), +(@PATH,18,2760.24,-4670.02,80.02687,0,0,0,0,100,0), +(@PATH,19,2770.4,-4660.86,86.92216,0,0,0,0,100,0), +(@PATH,20,2783.42,-4664.73,92.67192,0,0,0,0,100,0), +(@PATH,21,2797.51,-4678.94,95.49097,0,0,0,0,100,0), +(@PATH,22,2809.22,-4682.13,95.92142,0,0,0,0,100,0), +(@PATH,23,2826.65,-4680.09,90.41763,0,0,0,0,100,0), +(@PATH,24,2838.29,-4692.48,93.17684,0,0,0,0,100,0), +(@PATH,25,2853.44,-4706.6,89.93577,0,0,0,0,100,0), +(@PATH,26,2861.5,-4729.15,82.22752,0,0,0,0,100,0), +(@PATH,27,2855.89,-4746.56,81.98978,0,0,0,0,100,0); + +-- Pathing for Yetimus the Yeti Lord Entry: 47484 'TDB FORMAT' +SET @NPC := 323060; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-151.922,`position_y`=-171.311,`position_z`=104.9993 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-151.922,-171.311,104.9993,0,0,0,0,100,0), +(@PATH,2,-197.392,-164.851,92.99743,0,0,0,0,100,0), +(@PATH,3,-240.981,-167.431,80.67632,0,0,0,0,100,0), +(@PATH,4,-279.948,-174.962,74.14382,0,0,0,0,100,0), +(@PATH,5,-301.554,-187.203,68.3701,0,0,0,0,100,0), +(@PATH,6,-319.957,-198.203,64.63304,0,0,0,0,100,0), +(@PATH,7,-348.99,-235.068,62.78932,0,0,0,0,100,0), +(@PATH,8,-368.51,-265.285,60.20347,0,0,0,0,100,0), +(@PATH,9,-381.052,-305.778,59.71421,0,0,0,0,100,0), +(@PATH,10,-383.299,-340.087,59.16272,0,0,0,0,100,0), +(@PATH,11,-370.479,-366.644,58.37293,0,0,0,0,100,0), +(@PATH,12,-349.299,-399.33,58.9684,0,0,0,0,100,0), +(@PATH,13,-324.72,-430.033,59.33606,0,0,0,0,100,0), +(@PATH,14,-297.215,-456.95,60.7625,0,0,0,0,100,0), +(@PATH,15,-268.215,-460.696,64.35992,0,0,0,0,100,0), +(@PATH,16,-247.248,-462.217,65.86039,0,0,0,0,100,0), +(@PATH,17,-222.099,-464.127,67.62333,0,0,0,0,100,0), +(@PATH,18,-195.962,-466.226,71.86466,0,0,0,0,100,0), +(@PATH,19,-160.519,-459.127,76.6852,0,0,0,0,100,0), +(@PATH,20,-141.003,-451.144,76.6852,0,0,0,0,100,0), +(@PATH,21,-160.519,-459.127,76.6852,0,0,0,0,100,0), +(@PATH,22,-195.962,-466.226,71.86466,0,0,0,0,100,0), +(@PATH,23,-222.099,-464.127,67.62333,0,0,0,0,100,0), +(@PATH,24,-247.248,-462.217,65.86039,0,0,0,0,100,0), +(@PATH,25,-268.215,-460.696,64.35992,0,0,0,0,100,0), +(@PATH,26,-297.215,-456.95,60.7625,0,0,0,0,100,0), +(@PATH,27,-324.72,-430.033,59.33606,0,0,0,0,100,0), +(@PATH,28,-349.299,-399.33,58.9684,0,0,0,0,100,0), +(@PATH,29,-370.479,-366.644,58.37293,0,0,0,0,100,0), +(@PATH,30,-383.299,-340.087,59.16272,0,0,0,0,100,0), +(@PATH,31,-381.052,-305.778,59.71421,0,0,0,0,100,0), +(@PATH,32,-368.51,-265.285,60.20347,0,0,0,0,100,0), +(@PATH,33,-348.99,-235.068,62.78932,0,0,0,0,100,0), +(@PATH,34,-319.957,-198.203,64.63304,0,0,0,0,100,0), +(@PATH,35,-301.554,-187.203,68.3701,0,0,0,0,100,0), +(@PATH,36,-279.948,-174.962,74.14382,0,0,0,0,100,0), +(@PATH,37,-240.981,-167.431,80.67632,0,0,0,0,100,0), +(@PATH,38,-197.392,-164.851,92.99743,0,0,0,0,100,0); + +-- Pathing for Infernus Entry: 49266 'TDB FORMAT' +SET @NPC := 322294; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-573.0382,`position_y`=-1449.427,`position_z`=53.92358 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-573.0382,-1449.427,53.92358,0,0,0,0,100,0), +(@PATH,2,-561.0801,-1444.299,52.56591,0,0,0,0,100,0), +(@PATH,3,-554.1354,-1448.941,52.56591,0,0,0,0,100,0), +(@PATH,4,-552.0695,-1463.915,52.56591,0,0,0,0,100,0), +(@PATH,5,-553.8038,-1475.297,52.56591,0,0,0,0,100,0), +(@PATH,6,-565.9965,-1476.443,52.67285,0,0,0,0,100,0), +(@PATH,7,-573.3889,-1463.563,52.94677,0,0,0,0,100,0); + +-- Pathing for Teracula Entry: 49265 'TDB FORMAT' +SET @NPC := 322435; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-462.533,`position_y`=-1424.408,`position_z`=90.77872 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-462.533,-1424.408,90.77872,0,0,0,0,100,0), +(@PATH,2,-449.6858,-1420.599,96.06876,0,0,0,0,100,0), +(@PATH,3,-462.533,-1424.408,90.77872,0,0,0,0,100,0), +(@PATH,4,-477.5868,-1429.043,88.90503,0,0,0,0,100,0); diff --git a/sql/updates/world/4.3.4/2017_05_24_00_world.sql b/sql/updates/world/4.3.4/2017_05_24_00_world.sql new file mode 100644 index 0000000000..ae69db75f2 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_24_00_world.sql @@ -0,0 +1,325 @@ +-- Pathing for Stormwind Guard Entry: 1423 'TDB FORMAT' +SET @NPC := 281479; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-9621.585,`position_y`=-1009.805,`position_z`=41.4601 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,257,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9621.585,-1009.805,41.4601,0,0,0,0,100,0), +(@PATH,2,-9622.979,-993.5161,42.51941,0,0,0,0,100,0), +(@PATH,3,-9616.812,-971.4866,43.64319,0,0,0,0,100,0), +(@PATH,4,-9605.688,-952.9254,43.84697,0,0,0,0,100,0), +(@PATH,5,-9589.601,-935.541,43.71594,0,0,0,0,100,0), +(@PATH,6,-9581.84,-917.2405,43.88842,0,0,0,0,100,0), +(@PATH,7,-9582.131,-892.7952,43.52868,0,0,0,0,100,0), +(@PATH,8,-9587.052,-870.2479,43.77868,0,0,0,0,100,0), +(@PATH,9,-9603.133,-848.3824,43.8069,0,0,0,0,100,0), +(@PATH,10,-9635.435,-813.6964,43.84379,0,0,0,0,100,0), +(@PATH,11,-9646.747,-797.5594,43.59379,0,0,0,0,100,0), +(@PATH,12,-9651.212,-783.6508,44.32621,0,0,0,0,100,0), +(@PATH,13,-9651.457,-762.5749,44.47965,0,0,0,0,100,0), +(@PATH,14,-9656.33,-740.673,44.61954,0,0,0,0,100,0), +(@PATH,15,-9656.645,-723.0509,44.66413,0,0,0,0,100,0), +(@PATH,16,-9649.04,-701.8206,46.00813,0,0,0,0,100,0), +(@PATH,17,-9643.346,-663.4222,49.36496,0,0,0,0,100,0), +(@PATH,18,-9628.837,-641.6657,51.14138,0,0,0,0,100,0), +(@PATH,19,-9622.42,-603.7773,52.84998,0,0,0,0,100,0), +(@PATH,20,-9619.694,-574.7324,54.19883,0,0,0,0,100,0), +(@PATH,21,-9617.313,-551.6019,54.49004,0,0,0,0,100,0), +(@PATH,22,-9611.551,-532.0573,54.7783,0,0,0,0,100,0), +(@PATH,23,-9602.272,-517.8843,56.76878,0,0,0,0,100,0), +(@PATH,24,-9593.436,-504.3423,57.52607,0,0,0,0,100,0), +(@PATH,25,-9589.494,-487.5282,57.76851,0,0,0,0,100,0), +(@PATH,26,-9590.743,-469.7306,57.8166,0,0,0,0,100,0), +(@PATH,27,-9600.497,-453.0271,57.78099,0,0,0,0,100,0), +(@PATH,28,-9608.497,-436.1051,57.36327,0,0,0,0,100,0), +(@PATH,29,-9614.505,-416.2884,57.66486,0,0,0,0,100,0), +(@PATH,30,-9617.868,-395.8977,57.95574,0,0,0,0,100,0), +(@PATH,31,-9619.874,-371.5169,57.58074,0,0,0,0,100,0), +(@PATH,32,-9620.904,-344.161,57.28194,0,0,0,0,100,0), +(@PATH,33,-9620.884,-320.5441,57.52703,0,0,0,0,100,0), +(@PATH,34,-9618.642,-297.6285,57.18179,0,0,0,0,100,0), +(@PATH,35,-9612.653,-276.4153,57.76284,0,0,0,0,100,0), +(@PATH,36,-9608.691,-255.3432,57.32165,0,0,0,0,100,0), +(@PATH,37,-9598.686,-228.6033,57.3935,0,0,0,0,100,0), +(@PATH,38,-9588.345,-202.6797,57.81245,0,0,0,0,100,0), +(@PATH,39,-9578.535,-171.4949,57.50352,0,0,0,0,100,0), +(@PATH,40,-9567.966,-150.9942,57.1911,0,0,0,0,100,0), +(@PATH,41,-9553.459,-136.2681,57.28034,0,0,0,0,100,0), +(@PATH,42,-9549.182,-112.0365,57.55236,0,0,0,0,100,0), +(@PATH,43,-9548.437,-83.4119,57.64455,0,0,0,0,100,0), +(@PATH,44,-9546.561,-64.21647,57.19081,0,0,0,0,100,0), +(@PATH,45,-9542.052,-43.97417,56.69081,0,0,0,0,100,0), +(@PATH,46,-9531.666,-17.71886,56.00526,0,0,0,0,100,0), +(@PATH,47,-9518.505,4.58865,56.11089,0,0,0,0,100,0), +(@PATH,48,-9505.715,31.62967,56.48589,0,0,0,0,100,0), +(@PATH,49,-9495.036,54.66113,55.81353,0,0,0,0,100,0), +(@PATH,50,-9492.798,64.35981,56.02752,0,6000,0,0,100,0), +(@PATH,51,-9497.884,48.81619,55.94793,0,0,0,0,100,0), +(@PATH,52,-9503.121,36.35319,56.42255,0,0,0,0,100,0), +(@PATH,53,-9509.772,23.9451,56.53191,0,0,0,0,100,0), +(@PATH,54,-9517.83,6.747939,56.11089,0,0,0,0,100,0), +(@PATH,55,-9529.744,-15.72743,55.8871,0,0,0,0,100,0), +(@PATH,56,-9541.357,-44.91298,56.76772,0,0,0,0,100,0), +(@PATH,57,-9547.372,-71.95128,57.51955,0,0,0,0,100,0), +(@PATH,58,-9549.507,-109.4462,57.5067,0,0,0,0,100,0), +(@PATH,59,-9556.684,-136.5528,57.55939,0,0,0,0,100,0), +(@PATH,60,-9567.811,-151.0182,57.1723,0,0,0,0,100,0), +(@PATH,61,-9578.885,-170.2882,57.37852,0,0,0,0,100,0), +(@PATH,62,-9586.776,-195.1395,57.62852,0,0,0,0,100,0), +(@PATH,63,-9598.216,-224.6504,57.30341,0,0,0,0,100,0), +(@PATH,64,-9608.648,-258.0852,57.30822,0,0,0,0,100,0), +(@PATH,65,-9614.821,-289.097,57.59048,0,0,0,0,100,0), +(@PATH,66,-9618.106,-312.9915,57.58343,0,0,0,0,100,0), +(@PATH,67,-9620.264,-340.5638,57.52462,0,0,0,0,100,0), +(@PATH,68,-9619.762,-370.9549,57.58074,0,0,0,0,100,0), +(@PATH,69,-9618.118,-393.6722,57.83074,0,0,0,0,100,0), +(@PATH,70,-9610.834,-427.7363,57.52277,0,0,0,0,100,0), +(@PATH,71,-9602.774,-445.216,57.62401,0,0,0,0,100,0), +(@PATH,72,-9596.105,-461.7981,57.74839,0,0,0,0,100,0), +(@PATH,73,-9591.105,-476.2582,57.76851,0,0,0,0,100,0), +(@PATH,74,-9591.471,-488.4674,57.84004,0,0,0,0,100,0), +(@PATH,75,-9593.778,-501.4398,57.38178,0,0,0,0,100,0), +(@PATH,76,-9598.513,-512.4593,57.47431,0,0,0,0,100,0), +(@PATH,77,-9609.811,-533.6465,54.86504,0,0,0,0,100,0), +(@PATH,78,-9615.971,-550.82,54.49004,0,0,0,0,100,0), +(@PATH,79,-9618.966,-571.0148,54.37461,0,0,0,0,100,0), +(@PATH,80,-9620.506,-590.8423,53.78599,0,0,0,0,100,0), +(@PATH,81,-9623.524,-620.6938,51.94861,0,0,0,0,100,0), +(@PATH,82,-9628.995,-638.2269,51.17922,0,0,0,0,100,0), +(@PATH,83,-9636.7,-653.1119,49.69407,0,0,0,0,100,0), +(@PATH,84,-9641.278,-663.9442,49.39695,0,0,0,0,100,0), +(@PATH,85,-9645.316,-681.183,48.00885,0,0,0,0,100,0), +(@PATH,86,-9650.676,-701.9413,45.99372,0,0,0,0,100,0), +(@PATH,87,-9653.724,-722.3216,44.67292,0,0,0,0,100,0), +(@PATH,88,-9654.573,-742.368,44.55119,0,0,0,0,100,0), +(@PATH,89,-9652.612,-766.4833,44.30216,0,0,0,0,100,0), +(@PATH,90,-9648.009,-792.9749,43.62431,0,0,0,0,100,0), +(@PATH,91,-9638.621,-808.6445,43.71879,0,0,0,0,100,0), +(@PATH,92,-9626.769,-822.2813,43.88491,0,0,0,0,100,0), +(@PATH,93,-9613.571,-836.7086,43.62306,0,0,0,0,100,0), +(@PATH,94,-9600.535,-851.837,43.6819,0,0,0,0,100,0), +(@PATH,95,-9589.787,-865.6964,43.83097,0,0,0,0,100,0), +(@PATH,96,-9585.493,-875.5536,43.90368,0,0,0,0,100,0), +(@PATH,97,-9584.774,-898.893,43.90368,0,0,0,0,100,0), +(@PATH,98,-9586.063,-915.4184,43.90355,0,0,0,0,100,0), +(@PATH,99,-9592.028,-931.4844,43.74437,0,0,0,0,100,0), +(@PATH,100,-9598.08,-942.4412,43.92321,0,0,0,0,100,0), +(@PATH,101,-9607.78,-959.0113,43.49467,0,0,0,0,100,0), +(@PATH,102,-9615.448,-974.1688,43.85193,0,0,0,0,100,0), +(@PATH,103,-9620.891,-993.4722,42.6139,0,0,0,0,100,0), +(@PATH,104,-9620.597,-1003.663,42.25624,0,0,0,0,100,0), +(@PATH,105,-9620.338,-1014.109,41.06777,0,0,0,0,100,0), +(@PATH,106,-9619.945,-1024.693,40.49306,0,0,0,0,100,0), +(@PATH,107,-9619.242,-1036.472,39.87387,0,6000,0,0,100,0); + +-- Pathing for Stormwind Guard Entry: 1423 'TDB FORMAT' +SET @NPC := 280111; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-9083.599,`position_y`=-53.3508,`position_z`=86.42607 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,257,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9083.599,-53.3508,86.42607,0,0,0,0,100,0), +(@PATH,2,-9098.672,-65.61827,84.054,0,0,0,0,100,0), +(@PATH,3,-9109.419,-75.7207,82.09222,0,0,0,0,100,0), +(@PATH,4,-9125.424,-85.16591,78.16302,0,0,0,0,100,0), +(@PATH,5,-9142.284,-95.87967,75.0947,0,0,0,0,100,0), +(@PATH,6,-9163.195,-108.5354,72.56712,0,0,0,0,100,0), +(@PATH,7,-9176.171,-111.9833,71.24508,0,0,0,0,100,0), +(@PATH,8,-9195.773,-112.7946,71.12057,0,0,0,0,100,0), +(@PATH,9,-9208.957,-109.3175,71.1289,0,0,0,0,100,0), +(@PATH,10,-9225.822,-104.7172,71.1289,0,0,0,0,100,0), +(@PATH,11,-9238.654,-99.04698,70.70847,0,0,0,0,100,0), +(@PATH,12,-9249.91,-91.48221,70.40672,0,0,0,0,100,0), +(@PATH,13,-9268.238,-77.89268,68.6869,0,0,0,0,100,0), +(@PATH,14,-9280.204,-67.65853,68.24964,0,0,0,0,100,0), +(@PATH,15,-9297.876,-60.61285,67.34437,0,0,0,0,100,0), +(@PATH,16,-9322.913,-53.6008,66.44393,0,0,0,0,100,0), +(@PATH,17,-9335.962,-49.37478,65.8247,0,0,0,0,100,0), +(@PATH,18,-9351.479,-40.11382,64.81542,0,0,0,0,100,0), +(@PATH,19,-9362.026,-29.91482,63.76466,0,0,0,0,100,0), +(@PATH,20,-9376.168,-14.78429,62.24424,0,0,0,0,100,0), +(@PATH,21,-9397.745,6.895725,60.04395,0,0,0,0,100,0), +(@PATH,22,-9409.909,21.16298,58.82724,0,0,0,0,100,0), +(@PATH,23,-9438.457,54.57856,56.02,0,6000,0,0,100,0), +(@PATH,24,-9431.209,46.55914,56.69352,0,0,0,0,100,0), +(@PATH,25,-9421.634,36.47081,57.31852,0,0,0,0,100,0), +(@PATH,26,-9411.369,24.51682,58.24777,0,0,0,0,100,0), +(@PATH,27,-9401.32,13.38477,59.67916,0,0,0,0,100,0), +(@PATH,28,-9390.167,-1.145291,60.82187,0,0,0,0,100,0), +(@PATH,29,-9378.083,-13.01411,61.88828,0,0,0,0,100,0), +(@PATH,30,-9365.354,-27.72938,63.36524,0,0,0,0,100,0), +(@PATH,31,-9351.892,-40.30295,64.81542,0,0,0,0,100,0), +(@PATH,32,-9337.786,-50.15527,65.67455,0,0,0,0,100,0), +(@PATH,33,-9329.192,-52.84429,66.13094,0,0,0,0,100,0), +(@PATH,34,-9314.485,-56.48058,66.70492,0,0,0,0,100,0), +(@PATH,35,-9302.469,-59.14703,66.93221,0,0,0,0,100,0), +(@PATH,36,-9290.404,-63.35688,67.5221,0,0,0,0,100,0), +(@PATH,37,-9281.472,-69.32259,68.09779,0,0,0,0,100,0), +(@PATH,38,-9270.33,-77.17632,68.6869,0,0,0,0,100,0), +(@PATH,39,-9258.729,-86.89681,69.7136,0,0,0,0,100,0), +(@PATH,40,-9245.781,-95.48481,70.52708,0,0,0,0,100,0), +(@PATH,41,-9235.747,-101.5669,70.77646,0,0,0,0,100,0), +(@PATH,42,-9228.748,-104.1309,70.99169,0,0,0,0,100,0), +(@PATH,43,-9219.661,-106.7042,71.2539,0,0,0,0,100,0), +(@PATH,44,-9208.192,-109.8,71.17455,0,0,0,0,100,0), +(@PATH,45,-9197.428,-112.1889,71.09542,0,0,0,0,100,0), +(@PATH,46,-9185.816,-112.7407,70.99557,0,0,0,0,100,0), +(@PATH,47,-9174.032,-111.8417,71.54903,0,0,0,0,100,0), +(@PATH,48,-9159.315,-106.846,73.04197,0,0,0,0,100,0), +(@PATH,49,-9149.284,-100.6613,74.23655,0,0,0,0,100,0), +(@PATH,50,-9135.363,-91.4846,76.24387,0,0,0,0,100,0), +(@PATH,51,-9119.705,-80.96517,79.70452,0,0,0,0,100,0), +(@PATH,52,-9109.234,-73.00748,82.2177,0,0,0,0,100,0), +(@PATH,53,-9097.453,-63.84201,84.35332,0,0,0,0,100,0), +(@PATH,54,-9090.091,-58.36013,85.42094,0,0,0,0,100,0), +(@PATH,55,-9084.711,-52.9579,86.38237,0,0,0,0,100,0), +(@PATH,56,-9079.419,-48.8967,87.35429,0,0,0,0,100,0), +(@PATH,57,-9070.88,-43.41764,88.0645,0,6000,0,0,100,0); + +-- Pathing for Kira Songshine Entry: 3937 'TDB FORMAT' +SET @NPC := 280672; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-9493.627,`position_y`=67.18815,`position_z`=56.24675 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,257,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9493.627,67.18815,56.24675,0,0,0,0,100,0), +(@PATH,2,-9486.809,89.65723,56.21941,0,0,0,0,100,0), +(@PATH,3,-9483.946,102.302,56.50797,0,0,0,0,100,0), +(@PATH,4,-9480.245,126.3048,56.63297,0,0,0,0,100,0), +(@PATH,5,-9482.919,145.2651,56.43309,0,0,0,0,100,0), +(@PATH,6,-9485.429,167.3975,56.05416,0,0,0,0,100,0), +(@PATH,7,-9484.816,180.0712,55.42916,0,0,0,0,100,0), +(@PATH,8,-9493.019,196.9338,54.55416,0,0,0,0,100,0), +(@PATH,9,-9508.471,218.0667,52.96415,0,0,0,0,100,0), +(@PATH,10,-9533.104,242.1964,50.86973,0,0,0,0,100,0), +(@PATH,11,-9519.216,232.3553,51.83915,0,0,0,0,100,0), +(@PATH,12,-9515.605,227.5241,52.2238,0,0,0,0,100,0), +(@PATH,13,-9503.669,216.6386,52.90214,0,0,0,0,100,0), +(@PATH,14,-9498.017,202.3757,54.15273,0,0,0,0,100,0), +(@PATH,15,-9486.037,183.3565,55.22677,0,0,0,0,100,0), +(@PATH,16,-9483.614,166.1485,56.05247,0,0,0,0,100,0), +(@PATH,17,-9481.871,138.393,56.67747,0,0,0,0,100,0), +(@PATH,18,-9483.646,118.8074,56.60807,0,0,0,0,100,0), +(@PATH,19,-9486.335,100.2849,56.50797,0,0,0,0,100,0), +(@PATH,20,-9487.605,81.91924,56.0739,0,0,0,0,100,0), +(@PATH,21,-9485.286,71.61192,56.40178,0,0,0,0,100,0), +(@PATH,22,-9479.711,67.17296,56.32232,0,0,0,0,100,0), +(@PATH,23,-9467.877,61.33068,56.1054,0,0,0,0,100,0), +(@PATH,24,-9454.594,66.6288,56.20298,0,0,0,0,100,0), +(@PATH,25,-9415.596,86.5546,56.99038,0,0,0,0,100,0), +(@PATH,26,-9402.721,93.8989,58.41055,0,0,0,0,100,0), +(@PATH,27,-9383.628,105.0891,60.03624,0,0,0,0,100,0), +(@PATH,28,-9362.592,111.672,61.55702,0,0,0,0,100,0), +(@PATH,29,-9337.428,124.4685,63.71767,0,0,0,0,100,0), +(@PATH,30,-9316.489,136.0714,64.95474,0,0,0,0,100,0), +(@PATH,31,-9298.161,143.4155,65.91209,0,0,0,0,100,0), +(@PATH,32,-9273.096,151.2024,67.00413,0,0,0,0,100,0), +(@PATH,33,-9256.78,159.3222,67.66848,0,0,0,0,100,0), +(@PATH,34,-9242.877,174.1646,67.97204,0,0,0,0,100,0), +(@PATH,35,-9232.261,186.1395,67.72204,0,0,0,0,100,0), +(@PATH,36,-9217.805,203.6647,69.03122,0,0,0,0,100,0), +(@PATH,37,-9201.397,220.0502,71.15402,0,0,0,0,100,0), +(@PATH,38,-9188.232,236.8916,72.44244,0,0,0,0,100,0), +(@PATH,39,-9182.984,255.7783,73.85345,0,0,0,0,100,0), +(@PATH,40,-9182.252,275.1166,75.44212,0,0,0,0,100,0), +(@PATH,41,-9180.925,301.3294,78.33094,0,0,0,0,100,0), +(@PATH,42,-9178.171,323.0379,80.88319,0,0,0,0,100,0), +(@PATH,43,-9173.903,335.753,83.66998,0,0,0,0,100,0), +(@PATH,44,-9168.686,347.0231,86.27471,0,0,0,0,100,0), +(@PATH,45,-9142.421,375.9646,90.75526,0,0,0,0,100,0), +(@PATH,46,-9125.449,389.9619,91.57055,0,0,0,0,100,0), +(@PATH,47,-9144.014,376.6461,90.75526,0,0,0,0,100,0), +(@PATH,48,-9150.359,370.6424,90.63026,0,0,0,0,100,0), +(@PATH,49,-9159.769,358.9712,89.09229,0,0,0,0,100,0), +(@PATH,50,-9169.689,347.3052,86.06768,0,0,0,0,100,0), +(@PATH,51,-9176.393,336.1326,83.34795,0,0,0,0,100,0), +(@PATH,52,-9179.039,324.0334,81.12244,0,0,0,0,100,0), +(@PATH,53,-9181.582,310.6828,79.00208,0,0,0,0,100,0), +(@PATH,54,-9182.38,299.1464,77.95396,0,0,0,0,100,0), +(@PATH,55,-9183.653,286.0146,76.42735,0,0,0,0,100,0), +(@PATH,56,-9184.186,259.5755,74.10345,0,0,0,0,100,0), +(@PATH,57,-9187.476,239.7987,72.50726,0,0,0,0,100,0), +(@PATH,58,-9193.939,228.3685,71.82954,0,0,0,0,100,0), +(@PATH,59,-9217.061,204.2547,69.10202,0,0,0,0,100,0), +(@PATH,60,-9229.925,191.6477,68.03234,0,0,0,0,100,0), +(@PATH,61,-9239.118,181.4567,67.84704,0,0,0,0,100,0), +(@PATH,62,-9252.867,160.5058,67.88796,0,0,0,0,100,0), +(@PATH,63,-9270.517,152.484,67.12913,0,0,0,0,100,0), +(@PATH,64,-9281.984,150.6615,66.75413,0,0,0,0,100,0), +(@PATH,65,-9303.524,142.9477,65.81363,0,0,0,0,100,0), +(@PATH,66,-9326.493,133.6549,64.28152,0,0,0,0,100,0), +(@PATH,67,-9338.177,126.1314,63.79213,0,0,0,0,100,0), +(@PATH,68,-9357.066,114.8676,62.03004,0,0,0,0,100,0), +(@PATH,69,-9376.01,105.7821,60.5753,0,0,0,0,100,0), +(@PATH,70,-9396.483,100.0127,58.82322,0,0,0,0,100,0), +(@PATH,71,-9415.729,90.13653,57.42837,0,0,0,0,100,0), +(@PATH,72,-9430.02,79.53779,56.53139,0,0,0,0,100,0), +(@PATH,73,-9441.903,69.07547,56.12108,0,0,0,0,100,0), +(@PATH,74,-9459.128,61.95774,55.895,0,0,0,0,100,0), +(@PATH,75,-9471.797,63.62576,56.15252,0,0,0,0,100,0), +(@PATH,76,-9492.84,58.88786,55.85588,0,0,0,0,100,0), +(@PATH,77,-9502.176,40.73476,56.34699,0,0,0,0,100,0), +(@PATH,78,-9513.744,15.73003,56.48589,0,0,0,0,100,0), +(@PATH,79,-9519.953,3.746257,56.11089,0,0,0,0,100,0), +(@PATH,80,-9526.677,-8.577745,55.88026,0,0,0,0,100,0), +(@PATH,81,-9535.507,-27.89106,55.83387,0,0,0,0,100,0), +(@PATH,82,-9544.865,-53.43615,56.81581,0,0,0,0,100,0), +(@PATH,83,-9550.579,-84.43788,57.65163,0,0,0,0,100,0), +(@PATH,84,-9550.719,-113.8145,57.65856,0,0,0,0,100,0), +(@PATH,85,-9549.074,-80.8469,57.51955,0,0,0,0,100,0), +(@PATH,86,-9543.954,-52.83002,56.81581,0,0,0,0,100,0), +(@PATH,87,-9537.006,-30.56196,55.88392,0,0,0,0,100,0), +(@PATH,88,-9529.335,-14.98915,55.83778,0,0,0,0,100,0), +(@PATH,89,-9522.49,-4.730361,55.99379,0,0,0,0,100,0), +(@PATH,90,-9517.441,9.093316,56.23589,0,0,0,0,100,0), +(@PATH,91,-9508.014,28.54688,56.48589,0,0,0,0,100,0), +(@PATH,92,-9496.207,50.32487,55.88494,0,0,0,0,100,0); + +-- Pathing for Stormwind Royal Guard Entry: 1756 'TDB FORMAT' +SET @NPC := 314291; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-8415.07,`position_y`=299.125,`position_z`=147.0138 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,257,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-8415.07,299.125,147.0138,0,0,0,0,100,0), +(@PATH,2,-8409.74,292.457,147.2607,0,0,0,0,100,0), +(@PATH,3,-8389.694,267.0654,155.3475,0,0,0,0,100,0), +(@PATH,4,-8381.73,257.153,155.3472,0,0,0,0,100,0), +(@PATH,5,-8363.61,254.408,155.3472,0,0,0,0,100,0), +(@PATH,6,-8384.62,237.797,155.3471,0,0,0,0,100,0), +(@PATH,7,-8383.19,255.96,155.3434,0,0,0,0,100,0), +(@PATH,8,-8391.108,265.9411,155.3471,0,0,0,0,100,0), +(@PATH,9,-8411.21,291.196,147.2786,0,0,0,0,100,0), +(@PATH,10,-8417.51,299.163,147.0138,0,0,0,0,100,0), +(@PATH,11,-8434.2,321.583,145.1534,0,4000,0,0,100,0), +(@PATH,12,-8416.243,300.5492,147.0542,0,0,0,0,100,0), +(@PATH,13,-8401.91,311.34,147.0138,0,0,0,0,100,0), +(@PATH,14,-8399.65,329.141,147.0138,0,0,0,0,100,0), +(@PATH,15,-8381.1,327.168,147.0138,0,0,0,0,100,0), +(@PATH,16,-8383.38,308.866,147.0138,0,0,0,0,100,0), +(@PATH,17,-8401.068,310.4666,147.0138,0,0,0,0,100,0); + +-- Pathing for Stormwind City Guard Entry: 68 'TDB FORMAT' +SET @NPC := 313891; +SET @PATH := @NPC * 10; +UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-9144.325,`position_y`=374.0361,`position_z`=90.75526 WHERE `guid`=@NPC; +DELETE FROM `creature_addon` WHERE `guid`=@NPC; +INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,257,0, ''); +DELETE FROM `waypoint_data` WHERE `id`=@PATH; +INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES +(@PATH,1,-9144.325,374.0361,90.75526,0,0,0,0,100,0), +(@PATH,2,-9125.303,391.6143,91.78637,0,0,0,0,100,0), +(@PATH,3,-9091.403,414.3217,92.16946,0,0,0,0,100,0), +(@PATH,4,-9073.301,427.18,92.02811,0,0,0,0,100,0), +(@PATH,5,-9091.403,414.3217,92.16946,0,0,0,0,100,0), +(@PATH,6,-9125.303,391.6143,91.78637,0,0,0,0,100,0), +(@PATH,7,-9144.325,374.0361,90.75526,0,0,0,0,100,0), +(@PATH,8,-9165.44,351.6357,87.38135,0,0,0,0,100,0); diff --git a/sql/updates/world/4.3.4/2017_05_24_01_world.sql b/sql/updates/world/4.3.4/2017_05_24_01_world.sql new file mode 100644 index 0000000000..9904728dbb --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_24_01_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `creature_queststarter` WHERE `id` = 44906; diff --git a/sql/updates/world/4.3.4/2017_05_24_02_world.sql b/sql/updates/world/4.3.4/2017_05_24_02_world.sql new file mode 100644 index 0000000000..9e4912d13b --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_24_02_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128 WHERE `entry` = 42940; diff --git a/sql/updates/world/4.3.4/2017_05_26_00_world_from_335_was_2017_05_23_00_world.sql b/sql/updates/world/4.3.4/2017_05_26_00_world_from_335_was_2017_05_23_00_world.sql new file mode 100644 index 0000000000..635d13558d --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_26_00_world_from_335_was_2017_05_23_00_world.sql @@ -0,0 +1,2 @@ +-- correct typo in account set gmlevel command help +UPDATE `command` SET `help`="Syntax: .account set gmlevel [$account] #level [#realmID]\r\n\r\nSet the security level for targeted player (can't be used at self) or for account $name to a level of #level on the realm #realmID.\r\n\r\n#level may range from 0 to 3.\r\n\r\n#realmID may be -1 for all realms." WHERE `name`='account set gmlevel'; diff --git a/sql/updates/world/4.3.4/2017_05_26_01_world_from_335_was_2017_05_24_00_world.sql b/sql/updates/world/4.3.4/2017_05_26_01_world_from_335_was_2017_05_24_00_world.sql new file mode 100644 index 0000000000..5d9655ebf4 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_26_01_world_from_335_was_2017_05_24_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `quest_template_addon` SET `PrevQuestID`=12976 WHERE `id`=12977; diff --git a/sql/updates/world/4.3.4/2017_05_26_02_world_from_335_was_2017_05_24_01_world.sql b/sql/updates/world/4.3.4/2017_05_26_02_world_from_335_was_2017_05_24_01_world.sql new file mode 100644 index 0000000000..3830183971 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_26_02_world_from_335_was_2017_05_24_01_world.sql @@ -0,0 +1,9 @@ +-- +UPDATE `gameobject_addon` SET `invisibilityType`=9, `invisibilityValue`=1000 WHERE `guid`=270; +UPDATE `gameobject_addon` SET `invisibilityType`=8, `invisibilityValue`=1000 WHERE `guid`=21077; +UPDATE `gameobject_addon` SET `invisibilityType`=5, `invisibilityValue`=1000 WHERE `guid`=21079; +DELETE FROM `spell_area` WHERE `spell` IN (56773,56772,56774) AND `area`=4438; +INSERT INTO `spell_area` (`spell`, `area`, `quest_start`, `quest_end`, `aura_spell`, `racemask`, `gender`, `autocast`, `quest_start_status`, `quest_end_status`) VALUES +(56773, 4438, 12987, 0, 0, 0, 2, 1, 66, 0), +(56772, 4438, 13001, 0, 0, 0, 2, 1, 64, 0), +(56774, 4438, 12976, 0, 0, 0, 2, 1, 64, 0); diff --git a/sql/updates/world/4.3.4/2017_05_26_03_world_from_335_was_2017_05_25_00_world.sql b/sql/updates/world/4.3.4/2017_05_26_03_world_from_335_was_2017_05_25_00_world.sql new file mode 100644 index 0000000000..f8a1e0e2bf --- /dev/null +++ b/sql/updates/world/4.3.4/2017_05_26_03_world_from_335_was_2017_05_25_00_world.sql @@ -0,0 +1,7 @@ +UPDATE `smart_scripts` SET `link`=13 WHERE `entryorguid`=28213 AND `source_type`=0 AND `id`IN(8,10); +UPDATE `smart_scripts` SET `event_type`=7 WHERE `entryorguid`=28213 AND `source_type`=0 AND `id`=9 AND `link`=10; +DELETE FROM `smart_scripts` WHERE `entryorguid` =28213 AND `source_type`=0 AND `id`IN(13,14,6); +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`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(28213, 0, 13, 0, 61, 0, 100, 512, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Hardknuckle Matriarch - On Respawn - Set Passive'), +(28213, 0, 14, 0, 61, 0, 100, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 21, 500, 0, 0, 0, 0, 0, 0, 'Hardknuckle Matriarch - On Data Set 1 1 - Start Attacking'), +(28213, 0, 6, 14, 61, 0, 100, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Hardknuckle Matriarch - On Data Set 1 1 - Set Aggresive'); diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index 168bee50aa..1fc9682d5d 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -22,6 +22,7 @@ #include "VMapDefinitions.h" #include "Log.h" #include "Errors.h" +#include "Metric.h" #include #include @@ -347,6 +348,8 @@ namespace VMAP // currently, core creates grids for all maps, whether it has terrain tiles or not // so we need "fake" tile loads to know when we can unload map geometry iLoadedTiles[packTileID(tileX, tileY)] = false; + TC_METRIC_EVENT("map_events", "LoadMapTile", + "Map: " + std::to_string(iMapID) + " TileX: " + std::to_string(tileX) + " TileY: " + std::to_string(tileY)); return true; } if (!iTreeValues) @@ -473,6 +476,8 @@ namespace VMAP } } iLoadedTiles.erase(tile); + TC_METRIC_EVENT("map_events", "UnloadMapTile", + "Map: " + std::to_string(iMapID) + " TileX: " + std::to_string(tileX) + " TileY: " + std::to_string(tileY)); } void StaticMapTree::getModelInstances(ModelInstance* &models, uint32 &count) diff --git a/src/common/Common.h b/src/common/Common.h index c9fd940641..20c442f4c0 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -53,14 +53,14 @@ #include "Threading/LockedQueue.h" -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS # include -# if defined(__INTEL_COMPILER) +# if TRINITY_COMPILER == TRINITY_COMPILER_INTEL # if !defined(BOOST_ASIO_HAS_MOVE) # define BOOST_ASIO_HAS_MOVE # endif // !defined(BOOST_ASIO_HAS_MOVE) -# endif // if defined(__INTEL_COMPILER) +# endif // if TRINITY_COMPILER == TRINITY_COMPILER_INTEL #else # include @@ -71,7 +71,7 @@ # include #endif -#if COMPILER == COMPILER_MICROSOFT +#if TRINITY_COMPILER == TRINITY_COMPILER_MICROSOFT #include diff --git a/src/common/CompilerDefs.h b/src/common/CompilerDefs.h index 10db058953..0509dcf917 100644 --- a/src/common/CompilerDefs.h +++ b/src/common/CompilerDefs.h @@ -19,37 +19,37 @@ #ifndef TRINITY_COMPILERDEFS_H #define TRINITY_COMPILERDEFS_H -#define PLATFORM_WINDOWS 0 -#define PLATFORM_UNIX 1 -#define PLATFORM_APPLE 2 -#define PLATFORM_INTEL 3 +#define TRINITY_PLATFORM_WINDOWS 0 +#define TRINITY_PLATFORM_UNIX 1 +#define TRINITY_PLATFORM_APPLE 2 +#define TRINITY_PLATFORM_INTEL 3 // must be first (win 64 also define _WIN32) #if defined( _WIN64 ) -# define PLATFORM PLATFORM_WINDOWS +# define TRINITY_PLATFORM TRINITY_PLATFORM_WINDOWS #elif defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) -# define PLATFORM PLATFORM_WINDOWS +# define TRINITY_PLATFORM TRINITY_PLATFORM_WINDOWS #elif defined( __APPLE_CC__ ) -# define PLATFORM PLATFORM_APPLE +# define TRINITY_PLATFORM TRINITY_PLATFORM_APPLE #elif defined( __INTEL_COMPILER ) -# define PLATFORM PLATFORM_INTEL +# define TRINITY_PLATFORM TRINITY_PLATFORM_INTEL #else -# define PLATFORM PLATFORM_UNIX +# define TRINITY_PLATFORM TRINITY_PLATFORM_UNIX #endif -#define COMPILER_MICROSOFT 0 -#define COMPILER_GNU 1 -#define COMPILER_BORLAND 2 -#define COMPILER_INTEL 3 +#define TRINITY_COMPILER_MICROSOFT 0 +#define TRINITY_COMPILER_GNU 1 +#define TRINITY_COMPILER_BORLAND 2 +#define TRINITY_COMPILER_INTEL 3 #ifdef _MSC_VER -# define COMPILER COMPILER_MICROSOFT +# define TRINITY_COMPILER TRINITY_COMPILER_MICROSOFT #elif defined( __BORLANDC__ ) -# define COMPILER COMPILER_BORLAND +# define TRINITY_COMPILER TRINITY_COMPILER_BORLAND #elif defined( __INTEL_COMPILER ) -# define COMPILER COMPILER_INTEL +# define TRINITY_COMPILER TRINITY_COMPILER_INTEL #elif defined( __GNUC__ ) -# define COMPILER COMPILER_GNU +# define TRINITY_COMPILER TRINITY_COMPILER_GNU # define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #else # error "FATAL ERROR: Unknown compiler." diff --git a/src/common/Debugging/Errors.h b/src/common/Debugging/Errors.h index bf06d77d30..c21972af90 100644 --- a/src/common/Debugging/Errors.h +++ b/src/common/Debugging/Errors.h @@ -38,7 +38,7 @@ namespace Trinity } // namespace Trinity -#if COMPILER == COMPILER_MICROSOFT +#if TRINITY_COMPILER == TRINITY_COMPILER_MICROSOFT #define ASSERT_BEGIN __pragma(warning(push)) __pragma(warning(disable: 4127)) #define ASSERT_END __pragma(warning(pop)) #else diff --git a/src/common/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp index 09a027d167..5585dd25c1 100644 --- a/src/common/Debugging/WheatyExceptionReport.cpp +++ b/src/common/Debugging/WheatyExceptionReport.cpp @@ -5,7 +5,7 @@ //========================================== #include "CompilerDefs.h" -#if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__) +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS && !defined(__MINGW32__) #define WIN32_LEAN_AND_MEAN #pragma warning(disable:4996) #pragma warning(disable:4312) diff --git a/src/common/Debugging/WheatyExceptionReport.h b/src/common/Debugging/WheatyExceptionReport.h index aec52b165f..91c2ae9317 100644 --- a/src/common/Debugging/WheatyExceptionReport.h +++ b/src/common/Debugging/WheatyExceptionReport.h @@ -1,7 +1,7 @@ #ifndef _WHEATYEXCEPTIONREPORT_ #define _WHEATYEXCEPTIONREPORT_ -#if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__) +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS && !defined(__MINGW32__) #include #include diff --git a/src/common/Define.h b/src/common/Define.h index a109c5ba1d..c1aa331b0a 100644 --- a/src/common/Define.h +++ b/src/common/Define.h @@ -21,7 +21,7 @@ #include "CompilerDefs.h" -#if COMPILER == COMPILER_GNU +#if TRINITY_COMPILER == TRINITY_COMPILER_GNU # if !defined(__STDC_FORMAT_MACROS) # define __STDC_FORMAT_MACROS # endif @@ -55,7 +55,7 @@ # endif #endif -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS # define TRINITY_PATH_MAX MAX_PATH # define _USE_MATH_DEFINES # ifndef DECLSPEC_NORETURN @@ -64,11 +64,11 @@ # ifndef DECLSPEC_DEPRECATED # define DECLSPEC_DEPRECATED __declspec(deprecated) # endif //DECLSPEC_DEPRECATED -#else //PLATFORM != PLATFORM_WINDOWS +#else // TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS # define TRINITY_PATH_MAX PATH_MAX # define DECLSPEC_NORETURN # define DECLSPEC_DEPRECATED -#endif //PLATFORM +#endif // TRINITY_PLATFORM #if !defined(COREDEBUG) # define TRINITY_INLINE inline @@ -79,21 +79,21 @@ # define TRINITY_INLINE #endif //!COREDEBUG -#if COMPILER == COMPILER_GNU +#if TRINITY_COMPILER == TRINITY_COMPILER_GNU # define ATTR_NORETURN __attribute__((__noreturn__)) # define ATTR_PRINTF(F, V) __attribute__ ((__format__ (__printf__, F, V))) # define ATTR_DEPRECATED __attribute__((__deprecated__)) -#else //COMPILER != COMPILER_GNU +#else //TRINITY_COMPILER != TRINITY_COMPILER_GNU # define ATTR_NORETURN # define ATTR_PRINTF(F, V) # define ATTR_DEPRECATED -#endif //COMPILER == COMPILER_GNU +#endif //TRINITY_COMPILER == TRINITY_COMPILER_GNU #ifdef TRINITY_API_USE_DYNAMIC_LINKING -# if COMPILER == COMPILER_MICROSOFT +# if TRINITY_COMPILER == TRINITY_COMPILER_MICROSOFT # define TC_API_EXPORT __declspec(dllexport) # define TC_API_IMPORT __declspec(dllimport) -# elif COMPILER == COMPILER_GNU +# elif TRINITY_COMPILER == TRINITY_COMPILER_GNU # define TC_API_EXPORT __attribute__((visibility("default"))) # define TC_API_IMPORT # else diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index 702cd01d84..3e578cf1ee 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -41,17 +41,17 @@ char const* GitRevision::GetFullDatabase() return _FULL_DATABASE; } -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS # ifdef _WIN64 # define TRINITY_PLATFORM_STR "Win64" # else # define TRINITY_PLATFORM_STR "Win32" # endif -#elif PLATFORM == PLATFORM_APPLE +#elif TRINITY_PLATFORM == TRINITY_PLATFORM_APPLE # define TRINITY_PLATFORM_STR "MacOSX" -#elif PLATFORM == PLATFORM_INTEL +#elif TRINITY_PLATFORM == TRINITY_PLATFORM_INTEL # define TRINITY_PLATFORM_STR "Intel" -#else // PLATFORM_UNIX +#else // TRINITY_PLATFORM_UNIX # define TRINITY_PLATFORM_STR "Unix" #endif diff --git a/src/common/Logging/AppenderConsole.cpp b/src/common/Logging/AppenderConsole.cpp index e61cfdf30f..3378c185cc 100644 --- a/src/common/Logging/AppenderConsole.cpp +++ b/src/common/Logging/AppenderConsole.cpp @@ -21,7 +21,7 @@ #include "Config.h" #include "Util.h" -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS #include #endif @@ -66,7 +66,7 @@ void AppenderConsole::InitColors(std::string const& str) void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color) { -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS static WORD WinColorFG[MaxColors] = { 0, // BLACK @@ -153,7 +153,7 @@ void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color) void AppenderConsole::ResetColor(bool stdout_stream) { - #if PLATFORM == PLATFORM_WINDOWS + #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); #else diff --git a/src/common/Logging/AppenderFile.cpp b/src/common/Logging/AppenderFile.cpp index 8d9ea36bd5..6c68406667 100644 --- a/src/common/Logging/AppenderFile.cpp +++ b/src/common/Logging/AppenderFile.cpp @@ -20,7 +20,7 @@ #include "StringFormat.h" #include "Log.h" -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS # include #endif diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index 189971561f..fa67a8ea64 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -166,7 +166,7 @@ inline bool Log::ShouldLog(std::string const& type, LogLevel level) const } \ } -#if PLATFORM != PLATFORM_WINDOWS +#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS void check_args(const char*, ...) ATTR_PRINTF(1, 2); void check_args(std::string const&, ...); diff --git a/src/common/Metric/Metric.cpp b/src/common/Metric/Metric.cpp new file mode 100644 index 0000000000..7091dd0d37 --- /dev/null +++ b/src/common/Metric/Metric.cpp @@ -0,0 +1,235 @@ +/* +* Copyright (C) 2008-2017 TrinityCore +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 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 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 . +*/ + +#include "Metric.h" +#include "Log.h" +#include "Config.h" +#include "Util.h" + +void Metric::Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function overallStatusLogger) +{ + _realmName = FormatInfluxDBTagValue(realmName); + _batchTimer = Trinity::make_unique(ioService); + _overallStatusTimer = Trinity::make_unique(ioService); + _overallStatusLogger = overallStatusLogger; + LoadFromConfigs(); +} + +bool Metric::Connect() +{ + _dataStream.connect(_hostname, _port); + auto error = _dataStream.error(); + if (error) + { + TC_LOG_ERROR("metric", "Error connecting to '%s:%s', disabling Metric. Error message : %s", + _hostname.c_str(), _port.c_str(), error.message().c_str()); + _enabled = false; + return false; + } + _dataStream.clear(); + return true; +} + +void Metric::LoadFromConfigs() +{ + bool previousValue = _enabled; + _enabled = sConfigMgr->GetBoolDefault("Metric.Enable", false); + _updateInterval = sConfigMgr->GetIntDefault("Metric.Interval", 10); + if (_updateInterval < 1) + { + TC_LOG_ERROR("metric", "'Metric.Interval' config set to %d, overriding to 1.", _updateInterval); + _updateInterval = 1; + } + + _overallStatusTimerInterval = sConfigMgr->GetIntDefault("Metric.OverallStatusInterval", 1); + if (_overallStatusTimerInterval < 1) + { + TC_LOG_ERROR("metric", "'Metric.OverallStatusInterval' config set to %d, overriding to 1.", _overallStatusTimerInterval); + _overallStatusTimerInterval = 1; + } + + // Schedule a send at this point only if the config changed from Disabled to Enabled. + // Cancel any scheduled operation if the config changed from Enabled to Disabled. + if (_enabled && !previousValue) + { + std::string connectionInfo = sConfigMgr->GetStringDefault("Metric.ConnectionInfo", ""); + if (connectionInfo.empty()) + { + TC_LOG_ERROR("metric", "'Metric.ConnectionInfo' not specified in configuration file."); + return; + } + + Tokenizer tokens(connectionInfo, ';'); + if (tokens.size() != 3) + { + TC_LOG_ERROR("metric", "'Metric.ConnectionInfo' specified with wrong format in configuration file."); + return; + } + + _hostname.assign(tokens[0]); + _port.assign(tokens[1]); + _databaseName.assign(tokens[2]); + Connect(); + + ScheduleSend(); + ScheduleOverallStatusLog(); + } +} + +void Metric::Update() +{ + if (_overallStatusTimerTriggered) + { + _overallStatusTimerTriggered = false; + _overallStatusLogger(); + } +} + +void Metric::LogEvent(std::string const& category, std::string const& title, std::string const& description) +{ + using namespace std::chrono; + + MetricData* data = new MetricData; + data->Category = category; + data->Timestamp = system_clock::now(); + data->Type = METRIC_DATA_EVENT; + data->Title = title; + data->Text = description; + + _queuedData.Enqueue(data); +} + +void Metric::SendBatch() +{ + using namespace std::chrono; + + std::stringstream batchedData; + MetricData* data; + bool firstLoop = true; + while (_queuedData.Dequeue(data)) + { + if (!firstLoop) + batchedData << "\n"; + + batchedData << data->Category; + if (!_realmName.empty()) + batchedData << ",realm=" << _realmName; + + batchedData << " "; + + switch (data->Type) + { + case METRIC_DATA_VALUE: + batchedData << "value=" << data->Value; + break; + case METRIC_DATA_EVENT: + batchedData << "title=\"" << data->Title << "\",text=\"" << data->Text << "\""; + break; + } + + batchedData << " "; + + batchedData << std::to_string(duration_cast(data->Timestamp.time_since_epoch()).count()); + + firstLoop = false; + delete data; + } + + // Check if there's any data to send + if (batchedData.tellp() == std::streampos(0)) + { + ScheduleSend(); + return; + } + + if (!_dataStream.good() && !Connect()) + return; + + _dataStream << "POST " << "/write?db=" << _databaseName << " HTTP/1.1\r\n"; + _dataStream << "Host: " << _hostname << ":" << _port << "\r\n"; + _dataStream << "Accept: */*\r\n"; + _dataStream << "Content-Type: application/octet-stream\r\n"; + _dataStream << "Content-Transfer-Encoding: binary\r\n"; + + _dataStream << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n"; + _dataStream << batchedData.rdbuf(); + + std::string http_version; + _dataStream >> http_version; + unsigned int status_code = 0; + _dataStream >> status_code; + if (status_code != 204) + { + TC_LOG_ERROR("metric", "Error sending data, returned HTTP code: %u", status_code); + } + + // Read and ignore the status description + std::string status_description; + std::getline(_dataStream, status_description); + // Read headers + std::string header; + while (std::getline(_dataStream, header) && header != "\r") + { + if (header == "Connection: close\r") + _dataStream.close(); + } + + ScheduleSend(); +} + +void Metric::ScheduleSend() +{ + if (_enabled) + { + _batchTimer->expires_from_now(boost::posix_time::seconds(_updateInterval)); + _batchTimer->async_wait(std::bind(&Metric::SendBatch, this)); + } + else + { + _dataStream.close(); + MetricData* data; + // Clear the queue + while (_queuedData.Dequeue(data)) + ; + } +} + +void Metric::ForceSend() +{ + // Send what's queued only if io_service is stopped (so only on shutdown) + if (_enabled && _batchTimer->get_io_service().stopped()) + SendBatch(); +} + +void Metric::ScheduleOverallStatusLog() +{ + if (_enabled) + { + _overallStatusTimer->expires_from_now(boost::posix_time::seconds(_overallStatusTimerInterval)); + _overallStatusTimer->async_wait([this](const boost::system::error_code&) + { + _overallStatusTimerTriggered = true; + ScheduleOverallStatusLog(); + }); + } +} + +Metric* Metric::instance() +{ + static Metric instance; + return &instance; +} diff --git a/src/common/Metric/Metric.h b/src/common/Metric/Metric.h new file mode 100644 index 0000000000..8e4d129251 --- /dev/null +++ b/src/common/Metric/Metric.h @@ -0,0 +1,149 @@ +/* +* Copyright (C) 2008-2017 TrinityCore +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 2 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 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 . +*/ + +#ifndef METRIC_H__ +#define METRIC_H__ + +#include "Common.h" +#include "Threading/MPSCQueue.h" +#include +#include +#include + +enum MetricDataType +{ + METRIC_DATA_VALUE, + METRIC_DATA_EVENT +}; + +struct MetricData +{ + std::string Category; + std::chrono::time_point Timestamp; + MetricDataType Type; + + // LogValue-specific fields + std::string Value; + + // LogEvent-specific fields + std::string Title; + std::string Text; +}; + +class TC_COMMON_API Metric +{ +private: + boost::asio::ip::tcp::iostream _dataStream; + MPSCQueue _queuedData; + std::unique_ptr _batchTimer; + std::unique_ptr _overallStatusTimer; + int32 _updateInterval = 0; + int32 _overallStatusTimerInterval = 0; + bool _enabled = false; + bool _overallStatusTimerTriggered = false; + std::string _hostname; + std::string _port; + std::string _databaseName; + std::function _overallStatusLogger; + std::string _realmName; + + bool Connect(); + void SendBatch(); + void ScheduleSend(); + void ScheduleOverallStatusLog(); + + template::value>::type* = nullptr> + static std::string FormatInfluxDBValue(T value) { return std::to_string(value) + 'i'; } + + static std::string FormatInfluxDBValue(std::string const& value) + { + return '"' + boost::replace_all_copy(value, "\"", "\\\"") + '"'; + } + + static std::string FormatInfluxDBValue(bool value) { return value ? "t" : "f"; } + static std::string FormatInfluxDBValue(const char* value) { return FormatInfluxDBValue(std::string(value)); } + static std::string FormatInfluxDBValue(double value) { return std::to_string(value); } + static std::string FormatInfluxDBValue(float value) { return FormatInfluxDBValue(double(value)); } + + static std::string FormatInfluxDBTagValue(std::string const& value) + { + // ToDo: should handle '=' and ',' characters too + return boost::replace_all_copy(value, " ", "\\ "); + } + + // ToDo: should format TagKey and FieldKey too in the same way as TagValue + +public: + static Metric* instance(); + + void Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function overallStatusLogger = [](){}); + void LoadFromConfigs(); + void Update(); + + template + void LogValue(std::string const& category, T value) + { + using namespace std::chrono; + + MetricData* data = new MetricData; + data->Category = category; + data->Timestamp = system_clock::now(); + data->Type = METRIC_DATA_VALUE; + data->Value = FormatInfluxDBValue(value); + + _queuedData.Enqueue(data); + } + + void LogEvent(std::string const& category, std::string const& title, std::string const& description); + + void ForceSend(); + bool IsEnabled() const { return _enabled; } +}; + +#define sMetric Metric::instance() + +#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS +#define TC_METRIC_EVENT(category, title, description) \ + do { \ + if (sMetric->IsEnabled()) \ + sMetric->LogEvent(category, title, description); \ + } while (0) +#define TC_METRIC_VALUE(category, value) \ + do { \ + if (sMetric->IsEnabled()) \ + sMetric->LogValue(category, value); \ + } while (0) +#else +#define TC_METRIC_EVENT(category, title, description) \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + do { \ + if (sMetric->IsEnabled()) \ + sMetric->LogEvent(category, title, description); \ + } while (0) \ + __pragma(warning(pop)) +#define TC_METRIC_VALUE(category, value) \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + do { \ + if (sMetric->IsEnabled()) \ + sMetric->LogValue(category, value); \ + } while (0) \ + __pragma(warning(pop)) +#endif + +#endif // METRIC_H__ diff --git a/src/common/Threading/ProcessPriority.h b/src/common/Threading/ProcessPriority.h index 65332c6dff..b4ff3f5ecf 100644 --- a/src/common/Threading/ProcessPriority.h +++ b/src/common/Threading/ProcessPriority.h @@ -28,11 +28,6 @@ void SetProcessPriority(const std::string& logChannel) { -// Suppresses Mac OS X Warning since logChannel isn't used. -#if PLATFORM_APPLE - (void)logChannel; -#endif - #if defined(_WIN32) || defined(__linux__) ///- Handle affinity for multiple processors and process priority @@ -99,6 +94,9 @@ void SetProcessPriority(const std::string& logChannel) } #endif +#else + // Suppresses unused argument warning for all other platforms + (void)logChannel; #endif } diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 120218f585..36910246d1 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -24,7 +24,7 @@ #include #include -#if COMPILER == COMPILER_GNU +#if TRINITY_COMPILER == TRINITY_COMPILER_GNU #include #include #include @@ -421,7 +421,7 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension) bool utf8ToConsole(const std::string& utf8str, std::string& conStr) { -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS std::wstring wstr; if (!Utf8toWStr(utf8str, wstr)) return false; @@ -438,7 +438,7 @@ bool utf8ToConsole(const std::string& utf8str, std::string& conStr) bool consoleToUtf8(const std::string& conStr, std::string& utf8str) { -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS std::wstring wstr; wstr.resize(conStr.size()); OemToCharBuffW(&conStr[0], &wstr[0], uint32(conStr.size())); @@ -477,7 +477,7 @@ void utf8printf(FILE* out, const char *str, ...) void vutf8printf(FILE* out, const char *str, va_list* ap) { -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS char temp_buf[32 * 1024]; wchar_t wtemp_buf[32 * 1024]; diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index a911275ef2..1669e0958b 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -49,7 +49,7 @@ namespace fs = boost::filesystem; # define _TRINITY_REALM_CONFIG "authserver.conf" #endif -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS #include "ServiceWin32.h" char serviceName[] = "authserver"; char serviceLongName[] = "TrinityCore auth service"; @@ -90,7 +90,7 @@ int main(int argc, char** argv) if (vm.count("help") || vm.count("version")) return 0; -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS if (configService.compare("install") == 0) return WinServiceInstall() == true ? 0 : 1; else if (configService.compare("uninstall") == 0) @@ -163,7 +163,7 @@ int main(int argc, char** argv) // Set signal handlers boost::asio::signal_set signals(*_ioService, SIGINT, SIGTERM); -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS signals.add(SIGBREAK); #endif signals.async_wait(SignalHandler); @@ -182,7 +182,7 @@ int main(int argc, char** argv) _banExpiryCheckTimer->expires_from_now(boost::posix_time::seconds(_banExpiryCheckInterval)); _banExpiryCheckTimer->async_wait(BanExpiryHandler); -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS if (m_ServiceStatus != -1) { _serviceStatusWatchTimer = new boost::asio::deadline_timer(*_ioService); @@ -271,7 +271,7 @@ void BanExpiryHandler(boost::system::error_code const& error) } } -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS void ServiceStatusWatcher(boost::system::error_code const& error) { if (!error) @@ -299,7 +299,7 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, s ("config,c", value(&configFile)->default_value(fs::absolute(_TRINITY_REALM_CONFIG)), "use as configuration file") ; -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS options_description win("Windows platform specific options"); win.add_options() ("service,s", value(&configService)->default_value(""), "Windows service options: [install | uninstall]") diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp index 9c978588e5..d7cc5b13ef 100644 --- a/src/server/bnetserver/Main.cpp +++ b/src/server/bnetserver/Main.cpp @@ -53,7 +53,7 @@ namespace fs = boost::filesystem; # define _TRINITY_BNET_CONFIG "bnetserver.conf" #endif -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS #include "ServiceWin32.h" char serviceName[] = "bnetserver"; char serviceLongName[] = "TrinityCore bnet service"; @@ -147,7 +147,7 @@ int main(int argc, char** argv) // Set signal handlers boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS signals.add(SIGBREAK); #endif signals.async_wait(SignalHandler); diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index e50d17334f..2e33b665cb 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -52,7 +52,7 @@ BfWGCoordGY const WGGraveYard[BATTLEFIELD_WG_GRAVEYARD_MAX] = }; uint32 const ClockWorldState[] = { 3781, 4354 }; -uint32 const WintergraspFaction[] = { 1732, 1735, 35 }; +uint32 const WintergraspFaction[] = { FACTION_ALLIANCE_GENERIC_WG, FACTION_HORDE_GENERIC_WG, FACTION_FRIENDLY }; Position const WintergraspStalkerPos = { 4948.985f, 2937.789f, 550.5172f, 1.815142f }; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp index 1e99ead36e..394746cb6a 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAB.cpp @@ -399,7 +399,7 @@ void BattlegroundAB::_NodeOccupied(uint8 node, Team team) //aura should only apply to players who have accupied the node, set correct faction for trigger if (trigger) { - trigger->SetFaction(team == ALLIANCE ? 84 : 83); + trigger->SetFaction(team == ALLIANCE ? FACTION_ALLIANCE_GENERIC : FACTION_HORDE_GENERIC); trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); } } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index 6348513c08..81f31bb349 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -752,7 +752,7 @@ void BattlegroundAV::PopulateNode(BG_AV_Nodes node) DelCreature(node + 302); return; } - trigger->SetFaction(owner == ALLIANCE ? 84 : 83); + trigger->SetFaction(owner == ALLIANCE ? FACTION_ALLIANCE_GENERIC : FACTION_HORDE_GENERIC); trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); } } diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp index b196fb4fe6..4bf1dd15b3 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundEY.cpp @@ -783,7 +783,7 @@ void BattlegroundEY::EventTeamCapturedPoint(Player* player, uint32 Point) //aura should only apply to players who have accupied the node, set correct faction for trigger if (trigger) { - trigger->SetFaction(Team == ALLIANCE ? 84 : 83); + trigger->SetFaction(Team == ALLIANCE ? FACTION_ALLIANCE_GENERIC : FACTION_HORDE_GENERIC); trigger->CastSpell(trigger, SPELL_HONORABLE_DEFENDER_25Y, false); } } diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 382528d5b1..0dabb9ae40 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1888,7 +1888,7 @@ void GameObject::CastSpell(Unit* target, uint32 spellId, TriggerCastFlags trigge } else { - trigger->SetFaction(spellInfo->IsPositive() ? 35 : 14); + trigger->SetFaction(spellInfo->IsPositive() ? FACTION_FRIENDLY : FACTION_MONSTER); // Set owner guid for target if no owner available - needed by trigger auras // - trigger gets despawned and there's no caster avalible (see AuraEffect::TriggerSpell()) trigger->CastSpell(target ? target : trigger, spellInfo, triggered, nullptr, nullptr, target ? target->GetGUID() : ObjectGuid::Empty); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 7b186b715c..199b62f152 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2559,8 +2559,8 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid const& guid, uint32 npcflag if (creature->GetReactionTo(this) <= REP_UNFRIENDLY) return nullptr; - // not too far - if (!creature->IsWithinDistInMap(this, INTERACTION_DISTANCE)) + // not too far, taken from CGGameUI::SetInteractTarget + if (!creature->IsWithinDistInMap(this, creature->GetCombatReach() + 4.0f)) return nullptr; return creature; @@ -2568,33 +2568,36 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid const& guid, uint32 npcflag GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid) const { - if (GameObject* go = GetMap()->GetGameObject(guid)) - { - if (go->IsWithinDistInMap(this, go->GetInteractionDistance())) - return go; + if (!guid) + return nullptr; - TC_LOG_DEBUG("maps", "GetGameObjectIfCanInteractWith: GameObject '%s' [GUID: %u] is too far away from player %s [GUID: %u] to be used by him (distance=%f, maximal %f is allowed)", go->GetGOInfo()->name.c_str(), - go->GetGUID().GetCounter(), GetName().c_str(), GetGUID().GetCounter(), go->GetDistance(this), go->GetInteractionDistance()); - } + if (!IsInWorld()) + return nullptr; - return nullptr; + if (IsInFlight()) + return nullptr; + + // exist + GameObject* go = ObjectAccessor::GetGameObject(*this, guid); + if (!go) + return nullptr; + + if (!go->IsWithinDistInMap(this, go->GetInteractionDistance())) + return nullptr; + + return go; } GameObject* Player::GetGameObjectIfCanInteractWith(ObjectGuid const& guid, GameobjectTypes type) const { - if (GameObject* go = GetMap()->GetGameObject(guid)) - { - if (go->GetGoType() == type) - { - if (go->IsWithinDistInMap(this, go->GetInteractionDistance())) - return go; + GameObject* go = GetGameObjectIfCanInteractWith(guid); + if (!go) + return nullptr; - TC_LOG_DEBUG("maps", "Player::GetGameObjectIfCanInteractWith: GameObject '%s' (%s) is too far away from player '%s' (%s) to be used by him (Distance: %f, maximal 10 is allowed)", - go->GetGOInfo()->name.c_str(), go->GetGUID().ToString().c_str(), GetName().c_str(), GetGUID().ToString().c_str(), go->GetDistance(this)); - } - } + if (go->GetGoType() != type) + return nullptr; - return nullptr; + return go; } bool Player::IsUnderWater() const @@ -2648,13 +2651,13 @@ void Player::SetGameMaster(bool on) if (on) { m_ExtraFlags |= PLAYER_EXTRA_GM_ON; - SetFaction(35); + SetFaction(FACTION_FRIENDLY); SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GM); SetFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_CHEAT_SPELLS); if (Pet* pet = GetPet()) { - pet->SetFaction(35); + pet->SetFaction(FACTION_FRIENDLY); pet->getHostileRefManager().setOnlineOfflineState(false); } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 8db9e1b633..e0672d597c 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -49,6 +49,7 @@ #include "World.h" #include "WorldPacket.h" #include "WorldSession.h" +#include "Metric.h" #include "BattlenetServerManager.h" class LoginQueryHolder : public SQLQueryHolder @@ -1048,6 +1049,8 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder) sScriptMgr->OnPlayerLogin(pCurrChar, firstLogin); + TC_METRIC_EVENT("player_events", "Login", pCurrChar->GetName()); + sBattlenetServer.SendChangeToonOnlineState(GetBattlenetAccountId(), GetAccountId(), _player->GetGUID(), _player->GetName(), true); delete holder; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 56a155b5b9..0ef697f1eb 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -158,6 +158,51 @@ enum ReputationRank REP_EXALTED = 7 }; +enum FactionTemplates +{ + FACTION_NONE = 0, + FACTION_CREATURE = 7, + FACTION_ESCORTEE_A_NEUTRAL_PASSIVE = 10, + FACTION_MONSTER = 14, + FACTION_MONSTER_2 = 16, + FACTION_TROLL_BLOODSCALP = 28, + FACTION_PREY = 31, + FACTION_ESCORTEE_H_NEUTRAL_PASSIVE = 33, + FACTION_FRIENDLY = 35, + FACTION_OGRE = 45, + FACTION_ORC_DRAGONMAW = 62, + FACTION_HORDE_GENERIC = 83, + FACTION_ALLIANCE_GENERIC = 84, + FACTION_DEMON = 90, + FACTION_ELEMENTAL = 91, + FACTION_DRAGONFLIGHT_BLACK = 103, + FACTION_ESCORTEE_N_NEUTRAL_PASSIVE = 113, + FACTION_ENEMY = 168, + FACTION_ESCORTEE_A_NEUTRAL_ACTIVE = 231, + FACTION_ESCORTEE_H_NEUTRAL_ACTIVE = 232, + FACTION_ESCORTEE_N_NEUTRAL_ACTIVE = 250, + FACTION_ESCORTEE_N_FRIEND_PASSIVE = 290, + FACTION_TITAN = 415, + FACTION_ESCORTEE_N_FRIEND_ACTIVE = 495, + FACTION_GOBLIN_DARK_IRON_BAR_PATRON = 736, + FACTION_DARK_IRON_DWARVES = 754, + FACTION_ESCORTEE_A_PASSIVE = 774, + FACTION_ESCORTEE_H_PASSIVE = 775, + FACTION_UNDEAD_SCOURGE = 974, + FACTION_EARTHEN_RING = 1726, + FACTION_ALLIANCE_GENERIC_WG = 1732, + FACTION_HORDE_GENERIC_WG = 1735, + FACTION_ARAKKOA = 1738, + FACTION_ASHTONGUE_DEATHSWORN = 1820, + FACTION_FLAYER_HUNTER = 1840, + FACTION_MONSTER_SPAR_BUDDY = 1868, + FACTION_ESCORTEE_N_ACTIVE = 1986, + FACTION_ESCORTEE_H_ACTIVE = 2046, + FACTION_UNDEAD_SCOURGE_2 = 2068, + FACTION_UNDEAD_SCOURGE_3 = 2084, + FACTION_SCARLET_CRUSADE = 2089 +}; + #define MIN_REPUTATION_RANK (REP_HATED) #define MAX_REPUTATION_RANK 8 diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index c4233ffc34..b354ef9e74 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -26,6 +26,7 @@ #include "DisableMgr.h" #include "DetourCommon.h" #include "DetourNavMeshQuery.h" +#include "Metric.h" ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(const Unit* owner) : @@ -62,6 +63,8 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) return false; + TC_METRIC_EVENT("mmap_events", "CalculatePath", ""); + G3D::Vector3 dest(destX, destY, destZ); SetEndPosition(dest); diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp index edf56ecb5e..4fced58b5f 100644 --- a/src/server/game/Pools/PoolMgr.cpp +++ b/src/server/game/Pools/PoolMgr.cpp @@ -34,37 +34,32 @@ uint32 ActivePoolData::GetActiveObjectCount(uint32 pool_id) const // Method that tell if a creature is spawned currently template<> -bool ActivePoolData::IsActiveObject(uint32 db_guid) const +TC_GAME_API bool ActivePoolData::IsActiveObject(uint32 db_guid) const { return mSpawnedCreatures.find(db_guid) != mSpawnedCreatures.end(); } // Method that tell if a gameobject is spawned currently template<> -bool ActivePoolData::IsActiveObject(uint32 db_guid) const +TC_GAME_API bool ActivePoolData::IsActiveObject(uint32 db_guid) const { return mSpawnedGameobjects.find(db_guid) != mSpawnedGameobjects.end(); } // Method that tell if a pool is spawned currently template<> -bool ActivePoolData::IsActiveObject(uint32 sub_pool_id) const +TC_GAME_API bool ActivePoolData::IsActiveObject(uint32 sub_pool_id) const { return mSpawnedPools.find(sub_pool_id) != mSpawnedPools.end(); } // Method that tell if a quest can be started template<> -bool ActivePoolData::IsActiveObject(uint32 quest_id) const +TC_GAME_API bool ActivePoolData::IsActiveObject(uint32 quest_id) const { return mActiveQuests.find(quest_id) != mActiveQuests.end(); } -template TC_GAME_API bool ActivePoolData::IsActiveObject(uint32) const; -template TC_GAME_API bool ActivePoolData::IsActiveObject(uint32) const; -template TC_GAME_API bool ActivePoolData::IsActiveObject(uint32) const; -template TC_GAME_API bool ActivePoolData::IsActiveObject(uint32) const; - template<> void ActivePoolData::ActivateObject(uint32 db_guid, uint32 pool_id) { @@ -958,7 +953,6 @@ void PoolMgr::LoadFromDB() void PoolMgr::LoadQuestPools() { - } void PoolMgr::SaveQuestsToDB() diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp index 72f935e5cd..18b910420b 100644 --- a/src/server/game/Scripting/ScriptReloadMgr.cpp +++ b/src/server/game/Scripting/ScriptReloadMgr.cpp @@ -64,15 +64,10 @@ ScriptReloadMgr* ScriptReloadMgr::instance() namespace fs = boost::filesystem; -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS #include - #define HOTSWAP_PLATFORM_REQUIRES_CACHING -#elif __APPLE__ +#else // Posix and Apple #include - #define HOTSWAP_PLATFORM_REQUIRES_CACHING -#else // Posix - #include - // #define HOTSWAP_PLATFORM_REQUIRES_CACHING #endif // Promote the sScriptReloadMgr to a HotSwapScriptReloadMgr @@ -83,7 +78,7 @@ namespace fs = boost::filesystem; // Returns "" on Windows and "lib" on posix. static char const* GetSharedLibraryPrefix() { -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS return ""; #else // Posix return "lib"; @@ -93,16 +88,16 @@ static char const* GetSharedLibraryPrefix() // Returns "dll" on Windows, "dylib" on OS X, and "so" on posix. static char const* GetSharedLibraryExtension() { -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS return "dll"; -#elif __APPLE__ +#elif TRINITY_PLATFORM == TRINITY_PLATFORM_APPLE return "dylib"; #else // Posix return "so"; #endif } -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS typedef HMODULE HandleType; #else // Posix typedef void* HandleType; @@ -131,7 +126,7 @@ public: void operator() (HandleType handle) const { // Unload the associated shared library. -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS bool success = (FreeLibrary(handle) != 0); #else // Posix bool success = (dlclose(handle) == 0); @@ -241,7 +236,7 @@ private: template static bool GetFunctionFromSharedLibrary(HandleType handle, std::string const& name, Fn& fn) { -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS fn = reinterpret_cast(GetProcAddress(handle, name.c_str())); #else // Posix fn = reinterpret_cast(dlsym(handle, name.c_str())); @@ -260,7 +255,7 @@ Optional> return path; }(); -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS HandleType handle = LoadLibrary(load_path.generic_string().c_str()); #else // Posix HandleType handle = dlopen(load_path.generic_string().c_str(), RTLD_LAZY); @@ -404,7 +399,7 @@ static std::string CalculateScriptModuleProjectName(std::string const& module) /// could block the rebuild of new shared libraries. static bool IsDebuggerBlockingRebuild() { -#ifdef _WIN32 +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS if (IsDebuggerPresent()) return true; #endif @@ -609,8 +604,6 @@ public: } } - #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING - temporary_cache_path_ = CalculateTemporaryCachePath(); // We use the boost filesystem function versions which accept @@ -629,8 +622,6 @@ public: // Used to silent compiler warnings (void)code; - #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING - // Correct the CMake prefix when needed if (sWorld->getBoolConfig(CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED)) DoCMakePrefixCorrectionIfNeeded(); @@ -867,21 +858,17 @@ private: ASSERT(_running_script_module_names.find(path) == _running_script_module_names.end(), "Can't load a module which is running already!"); - Optional cache_path; - - #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING - - // Copy the shared library into a cache on platforms which lock files on use (windows). - cache_path = GenerateUniquePathForLibraryInCache(path); + // Copy the shared library into a cache + auto cache_path = GenerateUniquePathForLibraryInCache(path); { boost::system::error_code code; - fs::copy_file(path, *cache_path, fs::copy_option::fail_if_exists, code); + fs::copy_file(path, cache_path, fs::copy_option::fail_if_exists, code); if (code) { TC_LOG_FATAL("scripts.hotswap", ">> Failed to create cache entry for module " "\"%s\" at \"%s\" with reason (\"%s\")!", - path.filename().generic_string().c_str(), cache_path->generic_string().c_str(), + path.filename().generic_string().c_str(), cache_path.generic_string().c_str(), code.message().c_str()); // Find a better solution for this but it's much better @@ -892,11 +879,9 @@ private: } TC_LOG_TRACE("scripts.hotswap", ">> Copied the shared library \"%s\" to \"%s\" for caching.", - path.filename().generic_string().c_str(), cache_path->generic_string().c_str()); + path.filename().generic_string().c_str(), cache_path.generic_string().c_str()); } - #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING - auto module = ScriptModule::CreateFromPath(path, cache_path); if (!module) { @@ -1344,7 +1329,7 @@ private: auto current_path = fs::current_path(); - #ifndef _WIN32 + #if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS // The worldserver location is ${CMAKE_INSTALL_PREFIX}/bin // on all other platforms then windows current_path = current_path.parent_path(); diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h index ce4d4302e9..c67316eb64 100644 --- a/src/server/game/Scripting/ScriptSystem.h +++ b/src/server/game/Scripting/ScriptSystem.h @@ -12,30 +12,6 @@ class Creature; #define TEXT_SOURCE_RANGE -1000000 //the amount of entries each text source has available -/// @todo find better namings and definitions. -//N=Neutral, A=Alliance, H=Horde. -//NEUTRAL or FRIEND = Hostility to player surroundings (not a good definition) -//ACTIVE or PASSIVE = Hostility to environment surroundings. -enum eEscortFaction -{ - FACTION_ESCORT_A_NEUTRAL_PASSIVE = 10, - FACTION_ESCORT_H_NEUTRAL_PASSIVE = 33, - FACTION_ESCORT_N_NEUTRAL_PASSIVE = 113, - - FACTION_ESCORT_A_NEUTRAL_ACTIVE = 231, - FACTION_ESCORT_H_NEUTRAL_ACTIVE = 232, - FACTION_ESCORT_N_NEUTRAL_ACTIVE = 250, - - FACTION_ESCORT_N_FRIEND_PASSIVE = 290, - FACTION_ESCORT_N_FRIEND_ACTIVE = 495, - - FACTION_ESCORT_A_PASSIVE = 774, - FACTION_ESCORT_H_PASSIVE = 775, - - FACTION_ESCORT_N_ACTIVE = 1986, - FACTION_ESCORT_H_ACTIVE = 2046 -}; - struct ScriptPointMove { uint32 uiCreatureEntry; diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 9e5c9e2c90..d2db5848f8 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -47,6 +47,7 @@ #include "WardenWin.h" #include "WardenMac.h" #include "WardenMac.h" +#include "Metric.h" #include "BattlenetServerManager.h" #include @@ -422,6 +423,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater) break; } + TC_METRIC_VALUE("processed_packets", processedPackets); + _recvQueue.readd(requeuePackets.begin(), requeuePackets.end()); if (m_Socket && m_Socket->IsOpen() && _warden) @@ -578,6 +581,8 @@ void WorldSession::LogoutPlayer(bool save) //! Call script hook before deletion sScriptMgr->OnPlayerLogout(_player); + TC_METRIC_EVENT("player_events", "Logout", _player->GetName()); + //! Remove the player from the world // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 492b6891f7..d94b68e2bb 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -788,6 +788,14 @@ void Spell::SelectSpellTargets() if (m_spellInfo->IsChanneled()) { + // maybe do this for all spells? + if (m_UniqueTargetInfo.empty() && m_UniqueGOTargetInfo.empty() && m_UniqueItemInfo.empty() && !m_targets.HasDst()) + { + SendCastResult(SPELL_FAILED_BAD_IMPLICIT_TARGETS); + finish(false); + return; + } + uint8 mask = (1 << i); for (std::list::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) { diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp index e4b1af8935..4555326251 100644 --- a/src/server/game/Tools/PlayerDump.cpp +++ b/src/server/game/Tools/PlayerDump.cpp @@ -25,83 +25,370 @@ #include "AccountMgr.h" #include "World.h" -#define DUMP_TABLE_COUNT 34 +// static data +enum GuidType : uint8 +{ + // 32 bit long guids + GUID_TYPE_ACCOUNT, + GUID_TYPE_CHAR, + GUID_TYPE_PET, + GUID_TYPE_MAIL, + GUID_TYPE_ITEM, + + // 64 bit long guids + GUID_TYPE_EQUIPMENT_SET, + + // special types + GUID_TYPE_NULL // set to null +}; + +// for RAII +struct FileCloser +{ + void operator()(FILE* f) const + { + if (f) + fclose(f); + } +}; +typedef std::unique_ptr FileHandle; + +inline FileHandle GetFileHandle(char const* path, char const* mode) +{ + return FileHandle(fopen(path, mode), FileCloser()); +} + +struct BaseTable +{ + char const* TableName; + char const* PrimaryKey; + char const* PlayerGuid; + + GuidType StoredType; +}; + +BaseTable const BaseTables[] = +{ + { "character_pet", "id", "owner", GUID_TYPE_PET }, + { "mail", "id", "receiver", GUID_TYPE_MAIL }, + { "item_instance", "guid", "owner_guid", GUID_TYPE_ITEM }, + + { "character_equipmentsets", "setguid", "guid", GUID_TYPE_EQUIPMENT_SET } +}; + struct DumpTable { - char const* name; - DumpTableType type; + char const* Name; + DumpTableType Type; }; -DumpTable const dumpTables[DUMP_TABLE_COUNT] = +DumpTable const DumpTables[] = { - { "characters", DTT_CHARACTER }, - { "character_account_data", DTT_CHAR_TABLE }, - { "character_achievement", DTT_CHAR_TABLE }, - { "character_achievement_progress", DTT_CHAR_TABLE }, - { "character_action", DTT_CHAR_TABLE }, - { "character_aura", DTT_CHAR_TABLE }, - { "character_currency", DTT_CHAR_TABLE }, - { "character_cuf_profiles", DTT_CHAR_TABLE }, - { "character_declinedname", DTT_CHAR_TABLE }, - { "character_equipmentsets", DTT_EQSET_TABLE}, - { "character_fishingsteps", DTT_CHAR_TABLE }, - { "character_glyphs", DTT_CHAR_TABLE }, - { "character_homebind", DTT_CHAR_TABLE }, - { "character_inventory", DTT_INVENTORY }, - { "character_pet", DTT_PET }, - { "character_pet_declinedname", DTT_PET }, - { "character_queststatus", DTT_CHAR_TABLE }, - { "character_queststatus_daily", DTT_CHAR_TABLE }, - { "character_queststatus_weekly", DTT_CHAR_TABLE }, - { "character_queststatus_monthly", DTT_CHAR_TABLE }, - { "character_queststatus_seasonal", DTT_CHAR_TABLE }, - { "character_queststatus_rewarded", DTT_CHAR_TABLE }, - { "character_reputation", DTT_CHAR_TABLE }, - { "character_skills", DTT_CHAR_TABLE }, - { "character_spell", DTT_CHAR_TABLE }, - { "character_spell_cooldown", DTT_CHAR_TABLE }, - { "character_talent", DTT_CHAR_TABLE }, - { "mail", DTT_MAIL }, - { "mail_items", DTT_MAIL_ITEM }, // must be after mail - { "pet_aura", DTT_PET_TABLE }, // must be after character_pet - { "pet_spell", DTT_PET_TABLE }, // must be after character_pet - { "pet_spell_cooldown", DTT_PET_TABLE }, // must be after character_pet - { "item_instance", DTT_ITEM }, // must be after character_inventory and mail_items - { "character_gifts", DTT_ITEM_GIFT }, // must be after item_instance + { "characters", DTT_CHARACTER }, + { "character_account_data", DTT_CHAR_TABLE }, + { "character_achievement", DTT_CHAR_TABLE }, + { "character_achievement_progress", DTT_CHAR_TABLE }, + { "character_action", DTT_CHAR_TABLE }, + { "character_aura", DTT_CHAR_TABLE }, + { "character_currency", DTT_CHAR_TABLE }, + { "character_cuf_profiles", DTT_CHAR_TABLE }, + { "character_declinedname", DTT_CHAR_TABLE }, + { "character_equipmentsets", DTT_EQSET_TABLE}, + { "character_fishingsteps", DTT_CHAR_TABLE }, + { "character_glyphs", DTT_CHAR_TABLE }, + { "character_homebind", DTT_CHAR_TABLE }, + { "character_inventory", DTT_INVENTORY }, + { "character_pet", DTT_PET }, + { "character_pet_declinedname", DTT_PET }, + { "character_queststatus", DTT_CHAR_TABLE }, + { "character_queststatus_daily", DTT_CHAR_TABLE }, + { "character_queststatus_weekly", DTT_CHAR_TABLE }, + { "character_queststatus_monthly", DTT_CHAR_TABLE }, + { "character_queststatus_seasonal", DTT_CHAR_TABLE }, + { "character_queststatus_rewarded", DTT_CHAR_TABLE }, + { "character_reputation", DTT_CHAR_TABLE }, + { "character_skills", DTT_CHAR_TABLE }, + { "character_spell", DTT_CHAR_TABLE }, + { "character_spell_cooldown", DTT_CHAR_TABLE }, + { "character_talent", DTT_CHAR_TABLE }, + { "mail", DTT_MAIL }, + { "mail_items", DTT_MAIL_ITEM }, // must be after mail + { "pet_aura", DTT_PET_TABLE }, // must be after character_pet + { "pet_spell", DTT_PET_TABLE }, // must be after character_pet + { "pet_spell_cooldown", DTT_PET_TABLE }, // must be after character_pet + { "item_instance", DTT_ITEM }, // must be after character_inventory and mail_items + { "character_gifts", DTT_ITEM_GIFT }, // must be after item_instance }; +uint32 const DUMP_TABLE_COUNT = std::extent::value; + +// helper class to dump sql queries to a printable string +class StringTransaction +{ + public: + StringTransaction() : _buf() { } + + void Append(char const* sql) + { + std::ostringstream oss; + oss << sql << '\n'; + _buf += oss.str(); + } + + char const* GetBuffer() const + { + return _buf.c_str(); + } + + private: + std::string _buf; +}; + +// dynamic data, loaded at startup +struct TableField +{ + std::string FieldName; + + GuidType FieldGuidType = GUID_TYPE_ACCOUNT; + bool IsDependentField = false; +}; + +struct TableStruct +{ + std::string TableName; + std::string WhereFieldName; + std::vector TableFields; + + // for lookup + std::unordered_map FieldIndices; +}; + +std::vector CharacterTables; + +inline bool StringsEqualCaseInsensitive(std::string const& left, std::string const& right) +{ + std::string upperLeftString = left; + ASSERT(Utf8ToUpperOnlyLatin(upperLeftString)); + + std::string upperRightString = right; + ASSERT(Utf8ToUpperOnlyLatin(upperRightString)); + + return upperLeftString == upperRightString; +} + +inline auto FindColumnByName(TableStruct& tableStruct, std::string const& columnName) -> decltype(tableStruct.TableFields.begin()) +{ + return std::find_if(tableStruct.TableFields.begin(), tableStruct.TableFields.end(), [columnName](TableField const& tableField) -> bool + { + return StringsEqualCaseInsensitive(tableField.FieldName, columnName); + }); +} + +inline int32 GetColumnIndexByName(TableStruct const& tableStruct, std::string const& columnName) +{ + auto itr = tableStruct.FieldIndices.find(columnName); + if (itr == tableStruct.FieldIndices.end()) + return -1; + + return itr->second; +} + +inline void MarkDependentColumn(TableStruct& tableStruct, std::string const& columnName, GuidType dependentType) +{ + auto itr = FindColumnByName(tableStruct, columnName); + if (itr == tableStruct.TableFields.end()) + { + TC_LOG_FATAL("server.loading", "Column `%s` declared in table `%s` marked as dependent but doesn't exist, PlayerDump will not work properly, please update table definitions", + columnName.c_str(), tableStruct.TableName.c_str()); + ABORT(); + return; + } + + if (itr->IsDependentField) + { + TC_LOG_FATAL("server.loading", "Attempt to mark column `%s` in table `%s` as dependent column but already marked! please check your code.", + columnName.c_str(), tableStruct.TableName.c_str()); + ABORT(); + return; + } + + itr->IsDependentField = true; + itr->FieldGuidType = dependentType; +} + +inline void MarkWhereField(TableStruct& tableStruct, std::string const& whereField) +{ + ASSERT(tableStruct.WhereFieldName.empty()); + + auto whereFieldItr = FindColumnByName(tableStruct, whereField); + if (whereFieldItr == tableStruct.TableFields.end()) + { + TC_LOG_FATAL("server.loading", "Column name `%s` set as 'WHERE' column for table `%s` doesn't exist. PlayerDump won't work properly", + whereField.c_str(), tableStruct.TableName.c_str()); + ABORT(); + return; + } + + tableStruct.WhereFieldName = whereField; +} + +inline void AssertBaseTable(BaseTable const& baseTable) +{ + auto itr = std::find_if(CharacterTables.begin(), CharacterTables.end(), [baseTable](TableStruct const& tableStruct) -> bool + { + return StringsEqualCaseInsensitive(tableStruct.TableName, baseTable.TableName); + }); + + ASSERT(itr != CharacterTables.end()); + + auto columnItr = FindColumnByName(*itr, baseTable.PrimaryKey); + ASSERT(columnItr != itr->TableFields.end()); + + columnItr = FindColumnByName(*itr, baseTable.PlayerGuid); + ASSERT(columnItr != itr->TableFields.end()); +} + +void PlayerDump::InitializeTables() +{ + uint32 oldMSTime = getMSTime(); + + for (DumpTable const& dumpTable : DumpTables) + { + TableStruct t; + t.TableName = dumpTable.Name; + + QueryResult result = CharacterDatabase.PQuery("DESC %s", dumpTable.Name); + // prepared statement is correct (checked at startup) so table must exist + ASSERT(result); + + int32 i = 0; + do + { + std::string columnName = (*result)[0].GetString(); + t.FieldIndices.emplace(columnName, i++); + + TableField f; + f.FieldName = columnName; + + ASSERT(Utf8ToUpperOnlyLatin(columnName)); + + t.TableFields.emplace_back(std::move(f)); + } while (result->NextRow()); + + switch (dumpTable.Type) + { + case DTT_CHARACTER: + MarkWhereField(t, "guid"); + + MarkDependentColumn(t, "guid", GUID_TYPE_CHAR); + MarkDependentColumn(t, "account", GUID_TYPE_ACCOUNT); + + MarkDependentColumn(t, "deleteInfos_Account", GUID_TYPE_NULL); + MarkDependentColumn(t, "deleteInfos_Name", GUID_TYPE_NULL); + MarkDependentColumn(t, "deleteDate", GUID_TYPE_NULL); + break; + case DTT_CHAR_TABLE: + MarkWhereField(t, "guid"); + + MarkDependentColumn(t, "guid", GUID_TYPE_CHAR); + break; + case DTT_EQSET_TABLE: + MarkWhereField(t, "guid"); + + MarkDependentColumn(t, "guid", GUID_TYPE_CHAR); + MarkDependentColumn(t, "setguid", GUID_TYPE_EQUIPMENT_SET); + + // item0 - item18 + for (uint32 j = 0; j < EQUIPMENT_SLOT_END; ++j) + { + std::string itColumn = Trinity::StringFormat("item%u", j); + MarkDependentColumn(t, itColumn, GUID_TYPE_ITEM); + } + break; + case DTT_INVENTORY: + MarkWhereField(t, "guid"); + + MarkDependentColumn(t, "guid", GUID_TYPE_CHAR); + MarkDependentColumn(t, "bag", GUID_TYPE_ITEM); + MarkDependentColumn(t, "item", GUID_TYPE_ITEM); + break; + case DTT_MAIL: + MarkWhereField(t, "receiver"); + + MarkDependentColumn(t, "id", GUID_TYPE_MAIL); + MarkDependentColumn(t, "receiver", GUID_TYPE_CHAR); + break; + case DTT_MAIL_ITEM: + MarkWhereField(t, "mail_id"); + + MarkDependentColumn(t, "mail_id", GUID_TYPE_MAIL); + MarkDependentColumn(t, "item_guid", GUID_TYPE_ITEM); + MarkDependentColumn(t, "receiver", GUID_TYPE_CHAR); + break; + case DTT_ITEM: + MarkWhereField(t, "guid"); + + MarkDependentColumn(t, "guid", GUID_TYPE_ITEM); + MarkDependentColumn(t, "owner_guid", GUID_TYPE_CHAR); + break; + case DTT_ITEM_GIFT: + MarkWhereField(t, "item_guid"); + + MarkDependentColumn(t, "guid", GUID_TYPE_CHAR); + MarkDependentColumn(t, "item_guid", GUID_TYPE_ITEM); + break; + case DTT_PET: + MarkWhereField(t, "owner"); + + MarkDependentColumn(t, "id", GUID_TYPE_PET); + MarkDependentColumn(t, "owner", GUID_TYPE_CHAR); + break; + case DTT_PET_TABLE: + MarkWhereField(t, "guid"); + + MarkDependentColumn(t, "guid", GUID_TYPE_PET); + break; + default: + TC_LOG_FATAL("server.loading", "Wrong dump table type %u, probably added a new table type without updating code", uint32(dumpTable.Type)); + ABORT(); + return; + } + + CharacterTables.emplace_back(std::move(t)); + } + + // perform some sanity checks + for (TableStruct const& tableStruct : CharacterTables) + { + if (tableStruct.WhereFieldName.empty()) + { + TC_LOG_FATAL("server.loading", "Table `%s` defined in player dump doesn't have a WHERE query field", tableStruct.TableName.c_str()); + ABORT(); + } + } + + for (BaseTable const& baseTable : BaseTables) + AssertBaseTable(baseTable); + + ASSERT(CharacterTables.size() == DUMP_TABLE_COUNT); + + TC_LOG_INFO("server.loading", ">> Initialized tables for PlayerDump in %u ms.", GetMSTimeDiffToNow(oldMSTime)); +} + // Low level functions -static bool FindTokNth(std::string const& str, uint32 n, std::string::size_type& s, std::string::size_type& e) +inline bool FindColumn(TableStruct const& ts, std::string const& str, std::string const& column, std::string::size_type& s, std::string::size_type& e) { - s = e = 0; - - uint32 i = 1; - for (; s < str.size() && i < n; ++s) - if (str[s] == ' ') - ++i; - - if (i < n) + int32 columnIndex = GetColumnIndexByName(ts, column); + if (columnIndex == -1) return false; - e = str.find(' ', s); + // array indices start at 0, compensate + ++columnIndex; - return e != std::string::npos; -} - -std::string GetTokNth(std::string const& str, uint32 n) -{ - std::string::size_type s = 0, e = 0; - if (!FindTokNth(str, n, s, e)) - return ""; - - return str.substr(s, e - s); -} - -bool FindNth(std::string const& str, uint32 n, std::string::size_type& s, std::string::size_type& e) -{ - s = str.find("VALUES ('") + 9; + s = str.find("VALUES ('"); if (s == std::string::npos) return false; + s += 9; do { @@ -110,10 +397,11 @@ bool FindNth(std::string const& str, uint32 n, std::string::size_type& s, std::s return false; } while (str[e - 1] == '\\'); - for (uint32 i = 1; i < n; ++i) + for (int32 i = 1; i < columnIndex; ++i) { do { + // length of "', '" s = e + 4; e = str.find('\'', s); if (e == std::string::npos) @@ -123,8 +411,9 @@ bool FindNth(std::string const& str, uint32 n, std::string::size_type& s, std::s return true; } -std::string GetTableName(std::string const& str) +inline std::string GetTableName(std::string const& str) { + // length of "INSERT INTO `" static std::string::size_type const s = 13; std::string::size_type e = str.find(_TABLE_SIM_, s); if (e == std::string::npos) @@ -133,247 +422,310 @@ std::string GetTableName(std::string const& str) return str.substr(s, e - s); } -bool ChangeNth(std::string& str, uint32 n, char const* with, bool insert = false, bool allowZero = false) +inline bool ValidateFields(TableStruct const& ts, std::string const& str, size_t lineNumber) { - std::string::size_type s, e; - if (!FindNth(str, n, s, e)) + std::string::size_type s = str.find("` VALUES ("); + if (s != std::string::npos) // old dump format (no column names) + return true; + + // new format has insert with columns, need validation else we risk executing an invalid query + s = str.find("` (`"); + if (s == std::string::npos) + { + TC_LOG_ERROR("misc", "LoadPlayerDump: (line " UI64FMTD ") dump format not recognized.", lineNumber); return false; + } + s += 4; - if (allowZero && str.substr(s, e - s) == "0") - return true; // not an error - - if (!insert) - str.replace(s, e - s, with); - else - str.insert(s, with); - - return true; -} - -std::string GetNth(std::string& str, uint32 n) -{ - std::string::size_type s, e; - if (!FindNth(str, n, s, e)) - return ""; - - return str.substr(s, e-s); -} - -bool ChangeTokNth(std::string& str, uint32 n, char const* with, bool insert = false, bool allowZero = false) -{ - std::string::size_type s = 0, e = 0; - if (!FindTokNth(str, n, s, e)) + std::string::size_type valPos = str.find("VALUES ('"); + std::string::size_type e = str.find(_TABLE_SIM_, s); + if (e == std::string::npos || valPos == std::string::npos) + { + TC_LOG_ERROR("misc", "LoadPlayerDump: (line " UI64FMTD ") unexpected end of line", lineNumber); return false; - - if (allowZero && str.substr(s, e - s) == "0") - return true; // not an error - - if (!insert) - str.replace(s, e-s, with); - else - str.insert(s, with); - - return true; -} - -ObjectGuid::LowType RegisterNewGuid(ObjectGuid::LowType oldGuid, PlayerDump::DumpGuidMap& guidMap, ObjectGuid::LowType guidOffset) -{ - PlayerDumpWriter::DumpGuidMap::const_iterator itr = guidMap.find(oldGuid); - if (itr != guidMap.end()) - return itr->second; - - ObjectGuid::LowType newguid = guidOffset + guidMap.size(); - guidMap[oldGuid] = newguid; - return newguid; -} - -bool ChangeGuid(std::string& str, uint32 n, PlayerDump::DumpGuidMap& guidMap, ObjectGuid::LowType guidOffset, bool allowZero = false) -{ - ObjectGuid::LowType oldGuid = strtoull(GetNth(str, n).c_str(), nullptr, 10); - if (allowZero && !oldGuid) - return true; // not an error - - char chritem[20]; - ObjectGuid::LowType newGuid = RegisterNewGuid(oldGuid, guidMap, guidOffset); - snprintf(chritem, 20, "%u", newGuid); - - return ChangeNth(str, n, chritem, false, allowZero); -} - -std::string CreateDumpString(char const* tableName, QueryResult result) -{ - if (!tableName || !result) return ""; - std::ostringstream ss; - ss << "INSERT INTO " << _TABLE_SIM_ << tableName << _TABLE_SIM_ << " VALUES ("; - Field* fields = result->Fetch(); - for (uint32 i = 0; i < result->GetFieldCount(); ++i) - { - if (i == 0) ss << '\''; - else ss << ", '"; - - std::string s = fields[i].GetString(); - CharacterDatabase.EscapeString(s); - ss << s; - - ss << '\''; } - ss << ");"; - return ss.str(); -} - -std::string PlayerDumpWriter::GenerateWhereStr(char const* field, ObjectGuid::LowType guid) -{ - std::ostringstream wherestr; - wherestr << field << " = '" << guid << '\''; - return wherestr.str(); -} - -std::string PlayerDumpWriter::GenerateWhereStr(char const* field, DumpGuidSet const& guids, DumpGuidSet::const_iterator& itr) -{ - std::ostringstream wherestr; - wherestr << field << " IN ('"; - for (; itr != guids.end();) - { - wherestr << *itr; - ++itr; - - if (wherestr.str().size() > MAX_QUERY_LEN - 50) // near to max query - break; - - if (itr != guids.end()) - wherestr << "', '"; - } - wherestr << "')"; - return wherestr.str(); -} - -void StoreGUID(QueryResult result, uint32 field, PlayerDump::DumpGuidSet &guids) -{ - Field* fields = result->Fetch(); - ObjectGuid::LowType guid = fields[field].GetUInt32(); - if (guid) - guids.insert(guid); -} - -void StoreGUID(QueryResult result, uint32 data, uint32 field, PlayerDump::DumpGuidSet& guids) -{ - Field* fields = result->Fetch(); - std::string dataStr = fields[data].GetString(); - ObjectGuid::LowType guid = strtoull(GetTokNth(dataStr, field).c_str(), nullptr, 10); - if (guid) - guids.insert(guid); -} - -// Writing - High-level functions -bool PlayerDumpWriter::DumpTable(std::string& dump, ObjectGuid::LowType guid, char const* tableFrom, char const* tableTo, DumpTableType type) -{ - DumpGuidSet const* guids = nullptr; - char const* fieldname = nullptr; - - switch (type) - { - case DTT_ITEM: fieldname = "guid"; guids = &items; break; - case DTT_ITEM_GIFT: fieldname = "item_guid"; guids = &items; break; - case DTT_PET: fieldname = "owner"; break; - case DTT_PET_TABLE: fieldname = "guid"; guids = &pets; break; - case DTT_MAIL: fieldname = "receiver"; break; - case DTT_MAIL_ITEM: fieldname = "mail_id"; guids = &mails; break; - default: fieldname = "guid"; break; - } - - // for guid set stop if set is empty - if (guids && guids->empty()) - return true; // nothing to do - - // setup for guids case start position - DumpGuidSet::const_iterator guidsItr; - if (guids) - guidsItr = guids->begin(); do { - std::string wherestr; - - if (guids) // set case, get next guids string - wherestr = GenerateWhereStr(fieldname, *guids, guidsItr); - else // not set case, get single guid string - wherestr = GenerateWhereStr(fieldname, guid); - - QueryResult result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str()); - if (!result) - return true; - - do + std::string column = str.substr(s, e - s); + int32 columnIndex = GetColumnIndexByName(ts, column); + if (columnIndex == -1) { - // collect guids - switch (type) - { - case DTT_INVENTORY: - StoreGUID(result, 3, items); // item guid collection (character_inventory.item) - break; - case DTT_PET: - StoreGUID(result, 0, pets); // pet petnumber collection (character_pet.id) - break; - case DTT_MAIL: - StoreGUID(result, 0, mails); // mail id collection (mail.id) - break; - case DTT_MAIL_ITEM: - StoreGUID(result, 1, items); // item guid collection (mail_items.item_guid) - break; - case DTT_CHARACTER: - { - if (result->GetFieldCount() <= 69) // avoid crashes on next check - { - TC_LOG_FATAL("misc", "PlayerDumpWriter::DumpTable - Trying to access non-existing or wrong positioned field (`deleteInfos_Account`) in `characters` table."); - return false; - } - - if (result->Fetch()[69].GetUInt32()) // characters.deleteInfos_Account - if filled error - return false; - break; - } - default: - break; - } - - dump += CreateDumpString(tableTo, result); - dump += "\n"; + TC_LOG_ERROR("misc", "LoadPlayerDump: (line " UI64FMTD ") unknown column name `%s` for table `%s`, aborting due to incompatible DB structure.", lineNumber, column.c_str(), ts.TableName.c_str()); + return false; } - while (result->NextRow()); - } - while (guids && guidsItr != guids->end()); // not set case iterate single time, set case iterate for all guids + + // length of "`, `" + s = e + 4; + e = str.find(_TABLE_SIM_, s); + } while (e < valPos); + return true; } -bool PlayerDumpWriter::GetDump(ObjectGuid::LowType guid, std::string &dump) +inline bool ChangeColumn(TableStruct const& ts, std::string& str, std::string const& column, std::string const& with, bool allowZero = false) +{ + std::string::size_type s, e; + if (!FindColumn(ts, str, column, s, e)) + return false; + + if (allowZero && str.substr(s, e - s) == "0") + return true; // not an error + + str.replace(s, e - s, with); + return true; +} + +inline std::string GetColumn(TableStruct const& ts, std::string& str, std::string const& column) +{ + std::string::size_type s, e; + if (!FindColumn(ts, str, column, s, e)) + return ""; + + return str.substr(s, e - s); +} + +template class MapType, class... Rest> +inline T RegisterNewGuid(T oldGuid, MapType& guidMap, T guidOffset) +{ + auto itr = guidMap.find(oldGuid); + if (itr != guidMap.end()) + return itr->second; + + T newguid = guidOffset + T(guidMap.size()); + guidMap.emplace(oldGuid, newguid); + return newguid; +} + +template class MapType, class... Rest> +inline bool ChangeGuid(TableStruct const& ts, std::string& str, std::string const& column, MapType& guidMap, T guidOffset, bool allowZero = false) +{ + T oldGuid(atoull(GetColumn(ts, str, column).c_str())); + if (allowZero && !oldGuid) + return true; // not an error + + std::string chritem; + T newGuid = RegisterNewGuid(oldGuid, guidMap, guidOffset); + chritem = std::to_string(newGuid); + + return ChangeColumn(ts, str, column, chritem, allowZero); +} + +inline void AppendTableDump(StringTransaction& trans, TableStruct const& tableStruct, QueryResult result) +{ + if (!result) + return; + + do + { + std::ostringstream ss; + ss << "INSERT INTO " << _TABLE_SIM_ << tableStruct.TableName << _TABLE_SIM_ << " ("; + for (auto itr = tableStruct.TableFields.begin(); itr != tableStruct.TableFields.end();) + { + ss << _TABLE_SIM_ << itr->FieldName << _TABLE_SIM_; + ++itr; + + if (itr != tableStruct.TableFields.end()) + ss << ", "; + } + ss << ") VALUES ("; + + uint32 const fieldSize = uint32(tableStruct.TableFields.size()); + Field* fields = result->Fetch(); + + for (uint32 i = 0; i < fieldSize;) + { + char const* cString = fields[i].GetCString(); + ++i; + + // null pointer -> we have null + if (!cString) + ss << "'NULL'"; + else + { + std::string s(cString); + CharacterDatabase.EscapeString(s); + ss << '\'' << s << '\''; + } + + if (i != fieldSize) + ss << ", "; + } + ss << ");"; + + trans.Append(ss.str().c_str()); + } while (result->NextRow()); +} + +inline std::string GenerateWhereStr(std::string const& field, ObjectGuid::LowType guid) +{ + std::ostringstream whereStr; + whereStr << field << " = '" << guid << '\''; + return whereStr.str(); +} + +template class SetType, class... Rest> +inline std::string GenerateWhereStr(std::string const& field, SetType const& guidSet) +{ + std::ostringstream whereStr; + whereStr << field << " IN ('"; + for (auto itr = guidSet.begin(); itr != guidSet.end();) + { + whereStr << *itr; + ++itr; + + if (whereStr.str().size() > MAX_QUERY_LEN - 50) // near to max query + break; + + if (itr != guidSet.end()) + whereStr << "', '"; + } + whereStr << "')"; + return whereStr.str();; +} + +// Writing - High-level functions +void PlayerDumpWriter::PopulateGuids(ObjectGuid::LowType guid) +{ + for (BaseTable const& baseTable : BaseTables) + { + switch (baseTable.StoredType) + { + case GUID_TYPE_ITEM: + case GUID_TYPE_MAIL: + case GUID_TYPE_PET: + case GUID_TYPE_EQUIPMENT_SET: + break; + default: + return; + } + + std::string whereStr = GenerateWhereStr(baseTable.PlayerGuid, guid); + QueryResult result = CharacterDatabase.PQuery("SELECT %s FROM %s WHERE %s", baseTable.PrimaryKey, baseTable.TableName, whereStr.c_str()); + + if (!result) + continue; + + do + { + switch (baseTable.StoredType) + { + case GUID_TYPE_ITEM: + if (ObjectGuid::LowType guid = (*result)[0].GetUInt32()) + _items.insert(guid); + break; + case GUID_TYPE_MAIL: + if (ObjectGuid::LowType guid = (*result)[0].GetUInt32()) + _mails.insert(guid); + break; + case GUID_TYPE_PET: + if (ObjectGuid::LowType guid = (*result)[0].GetUInt32()) + _pets.insert(guid); + break; + case GUID_TYPE_EQUIPMENT_SET: + if (uint64 eqSetId = (*result)[0].GetUInt64()) + _itemSets.insert(eqSetId); + break; + default: + break; + } + } while (result->NextRow()); + } +} +bool PlayerDumpWriter::AppendTable(StringTransaction& trans, ObjectGuid::LowType guid, TableStruct const& tableStruct, DumpTable const& dumpTable) +{ + std::string whereStr; + switch (dumpTable.Type) + { + case DTT_ITEM: + case DTT_ITEM_GIFT: + if (_items.empty()) + return true; + + whereStr = GenerateWhereStr(tableStruct.WhereFieldName, _items); + break; + case DTT_PET_TABLE: + if (_pets.empty()) + return true; + + whereStr = GenerateWhereStr(tableStruct.WhereFieldName, _pets); + break; + case DTT_MAIL_ITEM: + if (_mails.empty()) + return true; + + whereStr = GenerateWhereStr(tableStruct.WhereFieldName, _mails); + break; + case DTT_EQSET_TABLE: + if (_itemSets.empty()) + return true; + + whereStr = GenerateWhereStr(tableStruct.WhereFieldName, _itemSets); + break; + default: + // not set case, get single guid string + whereStr = GenerateWhereStr(tableStruct.WhereFieldName, guid); + break; + } + + QueryResult result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", dumpTable.Name, whereStr.c_str()); + switch (dumpTable.Type) + { + case DTT_CHARACTER: + if (result) + { + // characters.deleteInfos_Account - if filled error + int32 index = GetColumnIndexByName(tableStruct, "deleteInfos_Account"); + ASSERT(index != -1); // checked at startup + + if ((*result)[index].GetUInt32()) + return false; + } + break; + default: + break; + + } + + AppendTableDump(trans, tableStruct, result); + return true; +} + +bool PlayerDumpWriter::GetDump(ObjectGuid::LowType guid, std::string& dump) { dump = "IMPORTANT NOTE: THIS DUMPFILE IS MADE FOR USE WITH THE 'PDUMP' COMMAND ONLY - EITHER THROUGH INGAME CHAT OR ON CONSOLE!\n"; dump += "IMPORTANT NOTE: DO NOT apply it directly - it will irreversibly DAMAGE and CORRUPT your database! You have been warned!\n\n"; - for (uint8 i = 0; i < DUMP_TABLE_COUNT; ++i) - if (!DumpTable(dump, guid, dumpTables[i].name, dumpTables[i].name, dumpTables[i].type)) + StringTransaction trans; + + // collect guids + PopulateGuids(guid); + for (uint32 i = 0; i < DUMP_TABLE_COUNT; ++i) + if (!AppendTable(trans, guid, CharacterTables[i], DumpTables[i])) return false; + dump += trans.GetBuffer(); + /// @todo Add instance/group.. /// @todo Add a dump level option to skip some non-important tables return true; } -DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, ObjectGuid::LowType guid) +DumpReturn PlayerDumpWriter::WriteDump(std::string const& file, ObjectGuid::LowType guid) { if (sWorld->getBoolConfig(CONFIG_PDUMP_NO_PATHS)) if (strstr(file.c_str(), "\\") || strstr(file.c_str(), "/")) return DUMP_FILE_OPEN_ERROR; if (sWorld->getBoolConfig(CONFIG_PDUMP_NO_OVERWRITE)) - if (FILE* f = fopen(file.c_str(), "r")) - { - fclose(f); + { + // check if file exists already + if (GetFileHandle(file.c_str(), "r")) return DUMP_FILE_OPEN_ERROR; - } + } - FILE* fout = fopen(file.c_str(), "w"); + FileHandle fout = GetFileHandle(file.c_str(), "w"); if (!fout) return DUMP_FILE_OPEN_ERROR; @@ -382,22 +734,19 @@ DumpReturn PlayerDumpWriter::WriteDump(const std::string& file, ObjectGuid::LowT if (!GetDump(guid, dump)) ret = DUMP_CHARACTER_DELETED; - fprintf(fout, "%s\n", dump.c_str()); - fclose(fout); + fprintf(fout.get(), "%s", dump.c_str()); return ret; } // Reading - High-level functions -#define ROLLBACK(DR) {fclose(fin); return (DR);} - -void fixNULLfields(std::string& line) +inline void FixNULLfields(std::string& line) { - static std::string const nullString("'NULL'"); - size_t pos = line.find(nullString); + static std::string const NullString("'NULL'"); + size_t pos = line.find(NullString); while (pos != std::string::npos) { - line.replace(pos, nullString.length(), "NULL"); - pos = line.find(nullString); + line.replace(pos, NullString.length(), "NULL"); + pos = line.find(NullString); } } @@ -407,11 +756,11 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s if (charcount >= 10) return DUMP_TOO_MANY_CHARS; - FILE* fin = fopen(file.c_str(), "r"); + FileHandle fin = GetFileHandle(file.c_str(), "r"); if (!fin) return DUMP_FILE_OPEN_ERROR; - char newguid[20], chraccount[20]; + std::string newguid, chraccount; // make sure the same guid doesn't already exist and is safe to use bool incHighest = true; @@ -419,9 +768,7 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_GUID); stmt->setUInt32(0, guid); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) guid = sObjectMgr->GetGenerator().GetNextAfterMaxUsed(); // use first free if exists else incHighest = false; @@ -429,7 +776,6 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s else guid = sObjectMgr->GetGenerator().GetNextAfterMaxUsed(); - // normalize the name if specified and check if it exists if (!normalizePlayerName(name)) name.clear(); @@ -438,241 +784,166 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, name); - PreparedQueryResult result = CharacterDatabase.Query(stmt); - - if (result) + if (PreparedQueryResult result = CharacterDatabase.Query(stmt)) name.clear(); // use the one from the dump } else name.clear(); // name encoded or empty + newguid = std::to_string(guid); + chraccount = std::to_string(account); - snprintf(newguid, 20, "%u", guid); - snprintf(chraccount, 20, "%u", account); + std::map items; + ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator().GetNextAfterMaxUsed(); - DumpGuidMap items; - DumpGuidMap mails; - char buf[32000]; - memset(buf, 0, sizeof(buf)); + std::map mails; + ObjectGuid::LowType mailLowGuidOffset = sObjectMgr->_mailId; - typedef std::map PetIds; - PetIds petIds; + std::map petIds; + ObjectGuid::LowType petLowGuidOffset = sObjectMgr->_hiPetNumber; + + std::map equipmentSetIds; + uint64 equipmentSetGuidOffset = sObjectMgr->_equipmentSetGuid; + + static size_t const BUFFER_SIZE = 32000; + char buf[BUFFER_SIZE] = { }; uint8 gender = GENDER_NONE; uint8 race = RACE_NONE; - uint8 playerClass = 0; + uint8 playerClass = CLASS_NONE; uint8 level = 1; - ObjectGuid::LowType itemLowGuidOffset = sObjectMgr->GetGenerator().GetNextAfterMaxUsed(); + // for logs + size_t lineNumber = 0; SQLTransaction trans = CharacterDatabase.BeginTransaction(); - while (!feof(fin)) + while (!feof(fin.get())) { - if (!fgets(buf, 32000, fin)) + if (!fgets(buf, BUFFER_SIZE, fin.get())) { - if (feof(fin)) + if (feof(fin.get())) break; - ROLLBACK(DUMP_FILE_BROKEN); + return DUMP_FILE_BROKEN; } - std::string line; line.assign(buf); + std::string line; + line.assign(buf); + ++lineNumber; // skip empty strings size_t nw_pos = line.find_first_not_of(" \t\n\r\7"); if (nw_pos == std::string::npos) continue; - // skip logfile-side dump start notice, the important notes and dump end notices - if ((line.substr(nw_pos, 16) == "== START DUMP ==") || - (line.substr(nw_pos, 15) == "IMPORTANT NOTE:") || - (line.substr(nw_pos, 14) == "== END DUMP ==")) + // skip the important notes + static std::string const SkippedLine = "IMPORTANT NOTE:"; + if (line.substr(nw_pos, SkippedLine.size()) == SkippedLine) continue; - // add required_ check - /* - if (line.substr(nw_pos, 41) == "UPDATE character_db_version SET required_") - { - if (!CharacterDatabase.Execute(line.c_str())) - ROLLBACK(DUMP_FILE_BROKEN); - - continue; - } - */ - // determine table name and load type std::string tn = GetTableName(line); if (tn.empty()) { - TC_LOG_ERROR("misc", "LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str()); - ROLLBACK(DUMP_FILE_BROKEN); + TC_LOG_ERROR("misc", "LoadPlayerDump: (line " UI64FMTD ") Can't extract table name!", lineNumber); + return DUMP_FILE_BROKEN; } - DumpTableType type = DumpTableType(0); - uint8 i; + DumpTableType type = DTT_CHARACTER; + uint32 i; for (i = 0; i < DUMP_TABLE_COUNT; ++i) { - if (tn == dumpTables[i].name) + if (tn == DumpTables[i].Name) { - type = dumpTables[i].type; + type = DumpTables[i].Type; break; } } if (i == DUMP_TABLE_COUNT) { - TC_LOG_ERROR("misc", "LoadPlayerDump: Unknown table: '%s'!", tn.c_str()); - ROLLBACK(DUMP_FILE_BROKEN); + TC_LOG_ERROR("misc", "LoadPlayerDump: (line " UI64FMTD ") Unknown table: `%s`!", lineNumber, tn.c_str()); + return DUMP_FILE_BROKEN; } - // change the data to server values + TableStruct const& ts = CharacterTables[i]; + if (!ValidateFields(ts, line, lineNumber)) + return DUMP_FILE_BROKEN; + + // per field guid offsetting + for (TableField const& field : ts.TableFields) + { + if (!field.IsDependentField) + continue; + + switch (field.FieldGuidType) + { + case GUID_TYPE_ACCOUNT: + if (!ChangeColumn(ts, line, field.FieldName, chraccount)) + return DUMP_FILE_BROKEN; + break; + case GUID_TYPE_CHAR: + if (!ChangeColumn(ts, line, field.FieldName, newguid)) + return DUMP_FILE_BROKEN; + break; + case GUID_TYPE_PET: + if (!ChangeGuid(ts, line, field.FieldName, petIds, petLowGuidOffset)) + return DUMP_FILE_BROKEN; + break; + case GUID_TYPE_MAIL: + if (!ChangeGuid(ts, line, field.FieldName, mails, mailLowGuidOffset)) + return DUMP_FILE_BROKEN; + break; + case GUID_TYPE_ITEM: + if (!ChangeGuid(ts, line, field.FieldName, items, itemLowGuidOffset, true)) + return DUMP_FILE_BROKEN; + break; + case GUID_TYPE_EQUIPMENT_SET: + if (!ChangeGuid(ts, line, field.FieldName, equipmentSetIds, equipmentSetGuidOffset)) + return DUMP_FILE_BROKEN; + break; + case GUID_TYPE_NULL: + { + static std::string const NullString("NULL"); + if (!ChangeColumn(ts, line, field.FieldName, NullString)) + return DUMP_FILE_BROKEN; + break; + } + } + } + + // extra modifications for other tables switch (type) { case DTT_CHARACTER: { - if (!ChangeNth(line, 1, newguid)) // characters.guid update - ROLLBACK(DUMP_FILE_BROKEN); - - if (!ChangeNth(line, 2, chraccount)) // characters.account update - ROLLBACK(DUMP_FILE_BROKEN); - - race = uint8(atoul(GetNth(line, 4).c_str())); - playerClass = uint8(atoul(GetNth(line, 5).c_str())); - gender = uint8(atoul(GetNth(line, 6).c_str())); - level = uint8(atoul(GetNth(line, 7).c_str())); + race = uint8(atoul(GetColumn(ts, line, "race").c_str())); + playerClass = uint8(atoul(GetColumn(ts, line, "class").c_str())); + gender = uint8(atoul(GetColumn(ts, line, "gender").c_str())); + level = uint8(atoul(GetColumn(ts, line, "level").c_str())); if (name.empty()) { // check if the original name already exists - name = GetNth(line, 3); + name = GetColumn(ts, line, "name"); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME); stmt->setString(0, name); PreparedQueryResult result = CharacterDatabase.Query(stmt); + // characters.at_login set to "rename on login" if (result) - if (!ChangeNth(line, 38, "1")) // characters.at_login set to "rename on login" - ROLLBACK(DUMP_FILE_BROKEN); + if (!ChangeColumn(ts, line, "at_login", "1")) + return DUMP_FILE_BROKEN; } - else if (!ChangeNth(line, 3, name.c_str())) // characters.name - ROLLBACK(DUMP_FILE_BROKEN); - - const char null[5] = "NULL"; - if (!ChangeNth(line, 68, null)) // characters.deleteInfos_Account - ROLLBACK(DUMP_FILE_BROKEN); - if (!ChangeNth(line, 69, null)) // characters.deleteInfos_Name - ROLLBACK(DUMP_FILE_BROKEN); - if (!ChangeNth(line, 70, null)) // characters.deleteDate - ROLLBACK(DUMP_FILE_BROKEN); - break; - } - case DTT_CHAR_TABLE: - { - if (!ChangeNth(line, 1, newguid)) // character_*.guid update - ROLLBACK(DUMP_FILE_BROKEN); - break; - } - case DTT_EQSET_TABLE: - { - if (!ChangeNth(line, 1, newguid)) - ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.guid - - char newSetGuid[24]; - snprintf(newSetGuid, 24, UI64FMTD, sObjectMgr->GenerateEquipmentSetGuid()); - if (!ChangeNth(line, 2, newSetGuid)) - ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.setguid - - for (uint8 slot = 0; slot < EQUIPMENT_SLOT_END; ++slot) - if (!ChangeGuid(line, 7 + slot, items, itemLowGuidOffset, true)) - ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.item - break; - } - case DTT_INVENTORY: - { - if (!ChangeNth(line, 1, newguid)) // character_inventory.guid update - ROLLBACK(DUMP_FILE_BROKEN); - - if (!ChangeGuid(line, 2, items, itemLowGuidOffset, true)) - ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.bag update - if (!ChangeGuid(line, 4, items, itemLowGuidOffset)) - ROLLBACK(DUMP_FILE_BROKEN); // character_inventory.item update - break; - } - case DTT_MAIL: // mail - { - if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId)) - ROLLBACK(DUMP_FILE_BROKEN); // mail.id update - if (!ChangeNth(line, 6, newguid)) // mail.receiver update - ROLLBACK(DUMP_FILE_BROKEN); - break; - } - case DTT_MAIL_ITEM: // mail_items - { - if (!ChangeGuid(line, 1, mails, sObjectMgr->_mailId)) - ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id - if (!ChangeGuid(line, 2, items, itemLowGuidOffset)) - ROLLBACK(DUMP_FILE_BROKEN); // mail_items.item_guid - if (!ChangeNth(line, 3, newguid)) // mail_items.receiver - ROLLBACK(DUMP_FILE_BROKEN); - break; - } - case DTT_ITEM: - { - // item, owner, data field:item, owner guid - if (!ChangeGuid(line, 1, items, itemLowGuidOffset)) - ROLLBACK(DUMP_FILE_BROKEN); // item_instance.guid update - if (!ChangeNth(line, 3, newguid)) // item_instance.owner_guid update - ROLLBACK(DUMP_FILE_BROKEN); - break; - } - case DTT_ITEM_GIFT: - { - if (!ChangeNth(line, 1, newguid)) // character_gifts.guid update - ROLLBACK(DUMP_FILE_BROKEN); - if (!ChangeGuid(line, 2, items, itemLowGuidOffset)) - ROLLBACK(DUMP_FILE_BROKEN); // character_gifts.item_guid update - break; - } - case DTT_PET: - { - // store a map of old pet id to new inserted pet id for use by DTT_PET_TABLE tables - std::string petIdStr = GetNth(line, 1); - - uint32 currentPetId = atoul(petIdStr.c_str()); - - PetIds::const_iterator petIdsItr = petIds.find(currentPetId); - if (petIdsItr != petIds.end()) // duplicate pets - ROLLBACK(DUMP_FILE_BROKEN); - - uint32 newPetId = sObjectMgr->GeneratePetNumber(); - petIds[currentPetId] = newPetId; - - if (!ChangeNth(line, 1, std::to_string(newPetId).c_str())) // character_pet.id update - ROLLBACK(DUMP_FILE_BROKEN); - if (!ChangeNth(line, 3, newguid)) // character_pet.owner update - ROLLBACK(DUMP_FILE_BROKEN); - - break; - } - case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown - { - std::string petIdStr = GetNth(line, 1); - - // lookup currpetid and match to new inserted pet id - PetIds::const_iterator petIdsItr = petIds.find(atoul(petIdStr.c_str())); - if (petIdsItr == petIds.end()) // couldn't find new inserted id - ROLLBACK(DUMP_FILE_BROKEN); - - if (!ChangeNth(line, 1, std::to_string(petIdsItr->second).c_str())) - ROLLBACK(DUMP_FILE_BROKEN); - + else if (!ChangeColumn(ts, line, "name", name.c_str())) // characters.name + return DUMP_FILE_BROKEN; break; } default: - TC_LOG_ERROR("misc", "Unknown dump table type: %u", type); break; } - fixNULLfields(line); + FixNULLfields(line); trans->Append(line.c_str()); } @@ -684,13 +955,12 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s sObjectMgr->GetGenerator().Set(sObjectMgr->GetGenerator().GetNextAfterMaxUsed() + items.size()); - sObjectMgr->_mailId += mails.size(); + sObjectMgr->_mailId += mails.size(); + sObjectMgr->_hiPetNumber += petIds.size(); + sObjectMgr->_equipmentSetGuid += equipmentSetIds.size(); if (incHighest) sObjectMgr->GetGenerator().Generate(); - - fclose(fin); - return DUMP_SUCCESS; } diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h index 3a5dfeb2e5..f6ada756ec 100644 --- a/src/server/game/Tools/PlayerDump.h +++ b/src/server/game/Tools/PlayerDump.h @@ -58,16 +58,18 @@ enum DumpReturn DUMP_SUCCESS, DUMP_FILE_OPEN_ERROR, DUMP_TOO_MANY_CHARS, - DUMP_UNEXPECTED_END, DUMP_FILE_BROKEN, DUMP_CHARACTER_DELETED }; +struct DumpTable; +struct TableStruct; +class StringTransaction; + class TC_GAME_API PlayerDump { public: - typedef std::set DumpGuidSet; - typedef std::map DumpGuidMap; + static void InitializeTables(); protected: PlayerDump() { } @@ -82,13 +84,14 @@ class TC_GAME_API PlayerDumpWriter : public PlayerDump DumpReturn WriteDump(std::string const& file, ObjectGuid::LowType guid); private: - bool DumpTable(std::string& dump, ObjectGuid::LowType guid, char const* tableFrom, char const* tableTo, DumpTableType type); - std::string GenerateWhereStr(char const* field, DumpGuidSet const& guids, DumpGuidSet::const_iterator& itr); - std::string GenerateWhereStr(char const* field, ObjectGuid::LowType guid); + bool AppendTable(StringTransaction& trans, ObjectGuid::LowType guid, TableStruct const& tableStruct, DumpTable const& dumpTable); + void PopulateGuids(ObjectGuid::LowType guid); - DumpGuidSet pets; - DumpGuidSet mails; - DumpGuidSet items; + std::set _pets; + std::set _mails; + std::set _items; + + std::set _itemSets; }; class TC_GAME_API PlayerDumpReader : public PlayerDump diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index d7f6255df9..9c44a7ea25 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -52,12 +52,14 @@ #include "ObjectMgr.h" #include "OutdoorPvPMgr.h" #include "Player.h" +#include "PlayerDump.h" #include "PoolMgr.h" #include "QueryCallback.h" #include "ScriptMgr.h" #include "ScriptReloadMgr.h" #include "SkillDiscovery.h" #include "SkillExtraItems.h" +#include "Metric.h" #include "SmartAI.h" #include "TicketMgr.h" #include "TransportMgr.h" @@ -396,6 +398,7 @@ void World::LoadConfigSettings(bool reload) return; } sLog->LoadFromConfig(); + sMetric->LoadFromConfigs(); } m_defaultDbcLocale = LocaleConstant(sConfigMgr->GetIntDefault("DBC.Locale", 0)); @@ -1225,7 +1228,7 @@ void World::LoadConfigSettings(bool reload) if (dataPath.empty() || (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\')) dataPath.push_back('/'); -#if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE +#if TRINITY_PLATFORM == TRINITY_PLATFORM_UNIX || TRINITY_PLATFORM == TRINITY_PLATFORM_APPLE if (dataPath[0] == '~') { const char* home = getenv("HOME"); @@ -1494,6 +1497,9 @@ void World::SetInitialWorldSettings() MMAP::MMapManager* mmmgr = MMAP::MMapFactory::createOrGetMMapManager(); mmmgr->InitializeThreadUnsafe(mapData); + TC_LOG_INFO("server.loading", "Initializing PlayerDump tables..."); + PlayerDump::InitializeTables(); + TC_LOG_INFO("server.loading", "Loading SpellInfo store..."); sSpellMgr->LoadSpellInfoStore(); @@ -2065,6 +2071,8 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000)); + TC_METRIC_EVENT("events", "World initialized", "World initialized in " + std::to_string(startupDuration / 60000) + " minutes " + std::to_string((startupDuration % 60000) / 1000) + " seconds"); + if (uint32 realmId = sConfigMgr->GetIntDefault("RealmID", 0)) // 0 reserved for auth sLog->SetRealmId(realmId); } @@ -2317,6 +2325,10 @@ void World::Update(uint32 diff) ProcessCliCommands(); sScriptMgr->OnWorldUpdate(diff); + + // Stats logger update + sMetric->Update(); + TC_METRIC_VALUE("update_time_diff", diff); } void World::ForceGameEventUpdate() diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp index 9b29d8c29b..a643d05fa9 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/blackrock_depths.cpp @@ -595,7 +595,7 @@ public: //spell by trap has effect61, this indicate the bar go hostile if (Unit* tmp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_PHALANX))) - tmp->SetFaction(14); + tmp->SetFaction(FACTION_MONSTER); //for later, this event(s) has alot more to it. //optionally, DONE can trigger bar to go hostile. diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp index b9e9e6186b..70173704fb 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp @@ -95,8 +95,6 @@ enum DirebrewEvents enum DirebrewMisc { - COREN_DIREBREW_FACTION_HOSTILE = 736, - COREN_DIREBREW_FACTION_FRIEND = 35, GOSSIP_ID = 11388, GO_MOLE_MACHINE_TRAP = 188509, GOSSIP_OPTION_FIGHT = 0, @@ -139,7 +137,7 @@ public: { _Reset(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetFaction(COREN_DIREBREW_FACTION_FRIEND); + me->SetFaction(FACTION_FRIENDLY); events.SetPhase(PHASE_ALL); for (uint8 i = 0; i < MAX_ANTAGONISTS; ++i) @@ -162,7 +160,7 @@ public: { events.SetPhase(PHASE_ONE); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetFaction(COREN_DIREBREW_FACTION_HOSTILE); + me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON); me->SetInCombatWithZone(); EntryCheckPredicate pred(NPC_ANTAGONIST); @@ -353,7 +351,7 @@ public: void Reset() override { - me->SetFaction(COREN_DIREBREW_FACTION_HOSTILE); + me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON); DoCastAOE(SPELL_MOLE_MACHINE_EMERGE, true); me->SetInCombatWithZone(); } @@ -395,7 +393,7 @@ public: break; case ACTION_ANTAGONIST_HOSTILE: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetFaction(COREN_DIREBREW_FACTION_HOSTILE); + me->SetFaction(FACTION_GOBLIN_DARK_IRON_BAR_PATRON); me->SetInCombatWithZone(); break; default: diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp index 56e7223654..b3b3a0f2b4 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_emperor_dagran_thaurissan.cpp @@ -73,7 +73,7 @@ class boss_emperor_dagran_thaurissan : public CreatureScript if (Creature* moira = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_MOIRA))) { moira->AI()->EnterEvadeMode(); - moira->SetFaction(35); + moira->SetFaction(FACTION_FRIENDLY); } } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp index 86ae8fdcce..b4ebc8b05a 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_tomb_of_seven.cpp @@ -134,7 +134,7 @@ class boss_doomrel : public CreatureScript case GOSSIP_ACTION_INFO_DEF+2: CloseGossipMenuFor(player); //start event here - creature->SetFaction(FACTION_HOSTILE); + creature->SetFaction(FACTION_DARK_IRON_DWARVES); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); creature->AI()->AttackStart(player); InstanceScript* instance = creature->GetInstanceScript(); @@ -170,7 +170,7 @@ class boss_doomrel : public CreatureScript { Initialize(); - me->SetFaction(FACTION_FRIEND); + me->SetFaction(FACTION_FRIENDLY); // was set before event start, so set again me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp index 8d2d316450..1bc8d78b79 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp @@ -351,7 +351,7 @@ public: { if (Creature* boss = instance->GetCreature(TombBossGUIDs[TombEventCounter])) { - boss->SetFaction(FACTION_HOSTILE); + boss->SetFaction(FACTION_DARK_IRON_DWARVES); boss->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); if (Unit* target = boss->SelectNearestTarget(500)) boss->AI()->AttackStart(target); @@ -377,7 +377,7 @@ public: boss->GetMotionMaster()->MoveTargetedHome(); boss->SetLootRecipient(NULL); } - boss->SetFaction(FACTION_FRIEND); + boss->SetFaction(FACTION_FRIENDLY); } } GhostKillCount = 0; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp index cbea54d1e1..4791f4ecf1 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp @@ -187,7 +187,7 @@ public: me->SetVisible(true); me->SetUInt32Value(UNIT_NPC_FLAGS, 1); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->SetStandState(UNIT_STAND_STATE_SIT_HIGH_CHAIR); me->RemoveAura(SPELL_NEFARIANS_BARRIER); } @@ -204,7 +204,7 @@ public: Talk(SAY_GAMESBEGIN_2); - me->SetFaction(103); + me->SetFaction(FACTION_DRAGONFLIGHT_BLACK); me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); DoCast(me, SPELL_NEFARIANS_BARRIER); me->SetStandState(UNIT_STAND_STATE_STAND); @@ -339,7 +339,7 @@ public: CreatureID = Entry[urand(0, 4)]; if (Creature* dragon = me->SummonCreature(CreatureID, DrakeSpawnLoc[i])) { - dragon->SetFaction(103); + dragon->SetFaction(FACTION_DRAGONFLIGHT_BLACK); dragon->AI()->AttackStart(me->GetVictim()); } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp index f890b5eddb..5ed364f0f0 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_vaelastrasz.cpp @@ -75,7 +75,7 @@ public: { Initialize(); creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - creature->SetFaction(35); + creature->SetFaction(FACTION_FRIENDLY); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); } @@ -153,7 +153,7 @@ public: events.ScheduleEvent(EVENT_SPEECH_4, 16000); break; case EVENT_SPEECH_4: - me->SetFaction(103); + me->SetFaction(FACTION_DRAGONFLIGHT_BLACK); if (Player* player = ObjectAccessor::GetPlayer(*me, PlayerGUID)) AttackStart(player); break; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp index c061ae2a42..c91b9bc813 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_majordomo_executus.cpp @@ -55,7 +55,6 @@ enum Spells enum Extras { OPTION_ID_YOU_CHALLENGED_US = 0, - FACTION_FRIENDLY = 35, MENU_OPTION_YOU_CHALLENGED_US = 4108 }; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index 57dc8f03f3..481472f854 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -173,7 +173,7 @@ class boss_ragnaros : public CreatureScript { //Become unbanished again me->SetReactState(REACT_AGGRESSIVE); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0); me->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); @@ -251,7 +251,7 @@ class boss_ragnaros : public CreatureScript me->InterruptNonMeleeSpells(false); //Root self //DoCast(me, 23973); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_SUBMERGED); me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp index 16fe9b7569..0130f7b9a8 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp @@ -1378,7 +1378,7 @@ void boss_julianne::boss_julianneAI::UpdateAI(uint32 diff) { Talk(SAY_JULIANNE_AGGRO); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFaction(16); + me->SetFaction(FACTION_MONSTER_2); AggroYellTimer = 0; } else AggroYellTimer -= diff; } @@ -1406,7 +1406,7 @@ void boss_julianne::boss_julianneAI::UpdateAI(uint32 diff) ENSURE_AI(boss_romulo::boss_romuloAI, pRomulo->AI())->Phase = PHASE_ROMULO; DoZoneInCombat(pRomulo); - pRomulo->SetFaction(16); + pRomulo->SetFaction(FACTION_MONSTER_2); } SummonedRomulo = true; } else SummonRomuloTimer -= diff; diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index 5b8fe23530..e8045f9405 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -460,7 +460,7 @@ public: Initialize(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); DoCast(me, SPELL_FLAMESTRIKE2, true); } @@ -666,7 +666,7 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetDisableGravity(true); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); DoCast(me, SPELL_ARCANE_SPHERE_PASSIVE, true); } diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp index f3038407da..774cf41fd1 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp @@ -125,7 +125,7 @@ public: { Initialize(); events.Reset(); - me->SetFaction(7); + me->SetFaction(FACTION_CREATURE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->SetStandState(UNIT_STAND_STATE_KNEEL); me->LoadEquipment(0, true); @@ -231,7 +231,7 @@ public: wait_timer -= diff; else { - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); phase = PHASE_ATTACKING; @@ -465,8 +465,7 @@ enum Says_VBM enum Misc_VBN { - QUEST_DEATH_CHALLENGE = 12733, - FACTION_HOSTILE = 2068 + QUEST_DEATH_CHALLENGE = 12733 }; class npc_death_knight_initiate : public CreatureScript @@ -585,7 +584,7 @@ public: { if (m_uiDuelTimer <= uiDiff) { - me->SetFaction(FACTION_HOSTILE); + me->SetFaction(FACTION_UNDEAD_SCOURGE_2); if (Unit* unit = ObjectAccessor::GetUnit(*me, m_uiDuelerGUID)) AttackStart(unit); @@ -771,7 +770,7 @@ public: { charmer->RemoveAurasDueToSpell(SPELL_EFFECT_STOLEN_HORSE); caster->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK); - caster->SetFaction(35); + caster->SetFaction(FACTION_FRIENDLY); DoCast(caster, SPELL_CALL_DARK_RIDER, true); if (Creature* Dark_Rider = me->FindNearestCreature(NPC_DARK_RIDER_OF_ACHERUS, 15)) ENSURE_AI(npc_dark_rider_of_acherus::npc_dark_rider_of_acherusAI, Dark_Rider->AI())->InitDespawnHorse(caster); diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index 396d5fb2fa..42c10ed929 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -649,7 +649,7 @@ public: { Unit* temp = me->SummonCreature(NPC_ACHERUS_GHOUL, (me->GetPositionX() - 20) + rand32() % 40, (me->GetPositionY() - 20) + rand32() % 40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); temp->SetWalk(false); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiGhoulGUID[uiSummon_counter] = temp->GetGUID(); ++uiSummon_counter; } @@ -667,7 +667,7 @@ public: { Unit* temp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, (me->GetPositionX() - 20) + rand32() % 40, (me->GetPositionY() - 20) + rand32() % 40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); temp->SetWalk(false); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiAbominationGUID[uiSummon_counter] = temp->GetGUID(); ++uiSummon_counter; } @@ -685,7 +685,7 @@ public: { Unit* temp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, (me->GetPositionX() - 20) + rand32() % 40, (me->GetPositionY() - 20) + rand32() % 40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); temp->SetWalk(false); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiWarriorGUID[uiSummon_counter] = temp->GetGUID(); ++uiSummon_counter; } @@ -703,7 +703,7 @@ public: { Unit* temp = me->SummonCreature(NPC_FLESH_BEHEMOTH, (me->GetPositionX() - 20) + rand32() % 40, (me->GetPositionY() - 20) + rand32() % 40, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); temp->SetWalk(false); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiBehemothGUID[uiSummon_counter] = temp->GetGUID(); ++uiSummon_counter; } @@ -1535,7 +1535,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_ACHERUS_GHOUL, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiGhoulGUID[i] = temp->GetGUID(); } } @@ -1545,7 +1545,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiAbominationGUID[i] = temp->GetGUID(); } } @@ -1555,7 +1555,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_RAMPAGING_ABOMINATION, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiWarriorGUID[i] = temp->GetGUID(); } } @@ -1565,7 +1565,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_FLESH_BEHEMOTH, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - temp->SetFaction(2084); + temp->SetFaction(FACTION_UNDEAD_SCOURGE_3); uiBehemothGUID[i] = temp->GetGUID(); } } @@ -1577,7 +1577,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - temp->SetFaction(2089); + temp->SetFaction(FACTION_SCARLET_CRUSADE); me->AddThreat(temp, 0.0f); uiDefenderGUID[i] = temp->GetGUID(); } @@ -1588,7 +1588,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - temp->SetFaction(2089); + temp->SetFaction(FACTION_SCARLET_CRUSADE); me->AddThreat(temp, 0.0f); uiEarthshatterGUID[i] = temp->GetGUID(); } @@ -1597,7 +1597,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - temp->SetFaction(2089); + temp->SetFaction(FACTION_SCARLET_CRUSADE); me->AddThreat(temp, 0.0f); uiKorfaxGUID = temp->GetGUID(); } @@ -1605,7 +1605,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - temp->SetFaction(2089); + temp->SetFaction(FACTION_SCARLET_CRUSADE); me->AddThreat(temp, 0.0f); uiMaxwellGUID = temp->GetGUID(); } @@ -1613,7 +1613,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); - temp->SetFaction(2089); + temp->SetFaction(FACTION_SCARLET_CRUSADE); me->AddThreat(temp, 0.0f); uiEligorGUID = temp->GetGUID(); } @@ -1621,7 +1621,7 @@ public: if (!temp) { temp = me->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); - temp->SetFaction(2089); + temp->SetFaction(FACTION_SCARLET_CRUSADE); me->AddThreat(temp, 0.0f); uiRayneGUID = temp->GetGUID(); } diff --git a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_apothecary_hummel.cpp b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_apothecary_hummel.cpp index 1ca23799f8..78f286c82c 100644 --- a/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_apothecary_hummel.cpp +++ b/src/server/scripts/EasternKingdoms/ShadowfangKeep/boss_apothecary_hummel.cpp @@ -74,8 +74,6 @@ enum ApothecaryMisc { ACTION_START_EVENT = 1, ACTION_START_FIGHT = 2, - FACTION_APOTHECARY_HOSTILE = 14, - FACTION_APOTHECARY_FRIENDLY = 35, GOSSIP_OPTION_START = 0, GOSSIP_MENU_HUMMEL = 10847, QUEST_YOUVE_BEEN_SERVED = 14488, @@ -115,7 +113,7 @@ class boss_apothecary_hummel : public CreatureScript _deadCount = 0; _isDead = false; events.SetPhase(PHASE_ALL); - me->SetFaction(FACTION_APOTHECARY_FRIENDLY); + me->SetFaction(FACTION_FRIENDLY); me->SummonCreatureGroup(1); } @@ -134,7 +132,7 @@ class boss_apothecary_hummel : public CreatureScript events.ScheduleEvent(EVENT_HUMMEL_SAY_0, Milliseconds(1)); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetFaction(FACTION_APOTHECARY_HOSTILE); + me->SetFaction(FACTION_MONSTER); DummyEntryCheckPredicate pred; summons.DoAction(ACTION_START_EVENT, pred); } @@ -289,7 +287,7 @@ struct npc_apothecary_genericAI : public ScriptedAI if (action == ACTION_START_EVENT) { me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetFaction(FACTION_APOTHECARY_HOSTILE); + me->SetFaction(FACTION_MONSTER); me->GetMotionMaster()->MovePoint(1, _movePos); } else if (action == ACTION_START_FIGHT) diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index 34289a5a41..5db76065f7 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -155,7 +155,7 @@ public: if (Creature* Sath = ObjectAccessor::GetCreature(*me, SathGUID)) Sath->AI()->EnterEvadeMode(); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); if (!bJustReset) //first reset at create { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); @@ -379,7 +379,7 @@ public: switch (TalkSequence) { case 1: - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); TalkTimer = 1000; break; case 2: diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index dd5f9c2bf9..6e4a1cbb0c 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -287,7 +287,7 @@ public: me->RemoveDynObject(SPELL_RING_OF_BLUE_FLAMES); for (uint8 i = 0; i < 4; ++i) if (GameObject* pOrb = GetOrb(i)) - pOrb->SetFaction(0); + pOrb->SetFaction(FACTION_NONE); } void EmpowerOrb(bool all) @@ -304,7 +304,7 @@ public: if (GameObject* pOrb = GetOrb(i)) { pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->SetFaction(35); + pOrb->SetFaction(FACTION_FRIENDLY); pOrb->setActive(true); pOrb->Refresh(); } @@ -316,7 +316,7 @@ public: if (GameObject* pOrb = GetOrb(urand(0, 3))) { pOrb->CastSpell(me, SPELL_RING_OF_BLUE_FLAMES); - pOrb->SetFaction(35); + pOrb->SetFaction(FACTION_FRIENDLY); pOrb->setActive(true); pOrb->Refresh(); @@ -369,7 +369,7 @@ public: InstanceScript* instance = go->GetInstanceScript(); player->SummonCreature(NPC_POWER_OF_THE_BLUE_DRAGONFLIGHT, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 121000); player->CastSpell(player, SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT, false); - go->SetFaction(0); + go->SetFaction(FACTION_NONE); if (Creature* pKalec = ObjectAccessor::GetCreature(*player, instance->GetGuidData(DATA_KALECGOS_KJ))) ENSURE_AI(boss_kalecgos_kj::boss_kalecgos_kjAI, pKalec->AI())->SetRingOfBlueFlames(); diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp index eae2d3a047..3e237a1876 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_archaedas.cpp @@ -96,7 +96,7 @@ class boss_archaedas : public CreatureScript Initialize(); instance->SetData(0, 5); // respawn any dead minions - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(true, UNIT_STATE_ROOT); me->AddAura(SPELL_FREEZE_ANIM, me); @@ -112,14 +112,14 @@ class boss_archaedas : public CreatureScript minion->CastSpell(minion, SPELL_ARCHAEDAS_AWAKEN, true); minion->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); minion->SetControlled(false, UNIT_STATE_ROOT); - minion->SetFaction(14); + minion->SetFaction(FACTION_MONSTER); minion->RemoveAura(SPELL_MINION_FREEZE_ANIM); } } void EnterCombat(Unit* /*who*/) override { - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(false, UNIT_STATE_ROOT); } @@ -259,7 +259,7 @@ class npc_archaedas_minions : public CreatureScript { Initialize(); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(true, UNIT_STATE_ROOT); me->RemoveAllAuras(); @@ -268,7 +268,7 @@ class npc_archaedas_minions : public CreatureScript void EnterCombat(Unit* /*who*/) override { - me->SetFaction (14); + me->SetFaction (FACTION_MONSTER); me->RemoveAllAuras(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(false, UNIT_STATE_ROOT); @@ -348,7 +348,7 @@ class npc_stonekeepers : public CreatureScript void Reset() override { - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(true, UNIT_STATE_ROOT); me->RemoveAllAuras(); @@ -357,7 +357,7 @@ class npc_stonekeepers : public CreatureScript void EnterCombat(Unit* /*who*/) override { - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetControlled(false, UNIT_STATE_ROOT); } diff --git a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp index 47b8d8d4ec..bd332448f2 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/instance_uldaman.cpp @@ -144,7 +144,7 @@ class instance_uldaman : public InstanceMapScript void SetFrozenState(Creature* creature) { - creature->SetFaction(35); + creature->SetFaction(FACTION_FRIENDLY); creature->RemoveAllAuras(); creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); creature->SetControlled(true, UNIT_STATE_ROOT); @@ -179,7 +179,7 @@ class instance_uldaman : public InstanceMapScript if (!target || !target->IsAlive()) continue; target->SetControlled(false, UNIT_STATE_ROOT); - target->SetFaction(14); + target->SetFaction(FACTION_MONSTER); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); target->RemoveAura(SPELL_MINION_FREEZE_ANIM); @@ -200,11 +200,11 @@ class instance_uldaman : public InstanceMapScript for (GuidVector::const_iterator i = archaedasWallMinions.begin(); i != archaedasWallMinions.end(); ++i) { Creature* target = instance->GetCreature(*i); - if (!target || !target->IsAlive() || target->GetFaction() == 14) + if (!target || !target->IsAlive() || target->GetFaction() == FACTION_MONSTER) continue; target->SetControlled(false, UNIT_STATE_ROOT); target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - target->SetFaction(14); + target->SetFaction(FACTION_MONSTER); target->RemoveAura(SPELL_MINION_FREEZE_ANIM); archaedas->CastSpell(target, SPELL_AWAKEN_VAULT_WALKER, true); target->CastSpell(target, SPELL_ARCHAEDAS_AWAKEN, true); @@ -267,7 +267,7 @@ class instance_uldaman : public InstanceMapScript if (!ironaya) return; - ironaya->SetFaction(415); + ironaya->SetFaction(FACTION_TITAN); ironaya->SetControlled(false, UNIT_STATE_ROOT); ironaya->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp index 9c361a97ff..40de85ea67 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -196,7 +196,7 @@ class boss_akilzon : public CreatureScript y = 1380.0f + rand32() % 60; if (Unit* trigger = me->SummonTrigger(x, y, z, 0, 2000)) { - trigger->SetFaction(35); + trigger->SetFaction(FACTION_FRIENDLY); trigger->SetMaxHealth(100000); trigger->SetHealth(100000); trigger->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); @@ -291,7 +291,7 @@ class boss_akilzon : public CreatureScript Cloud->SetDisableGravity(true); Cloud->StopMoving(); Cloud->SetObjectScale(1.0f); - Cloud->SetFaction(35); + Cloud->SetFaction(FACTION_FRIENDLY); Cloud->SetMaxHealth(9999999); Cloud->SetHealth(9999999); Cloud->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp index 1cfd0ea67d..732c0fed94 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp @@ -89,9 +89,7 @@ enum Misc { POINT_START_REVIVE = 1, - DATA_OHGANOT_SO_FAST = 5762, - - FACTION_NONE = 1665 + DATA_OHGANOT_SO_FAST = 5762 }; enum SummonGroups diff --git a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp index 33ca93739c..533031aed4 100644 --- a/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp @@ -57,8 +57,7 @@ enum ProfessorPhizzlethorpe QUEST_SUNKEN_TREASURE = 665, QUEST_GOGGLE_BOGGLE = 26050, // Creatures - NPC_VENGEFUL_SURGE = 2776, - FACTION_SUNKEN_TREASURE = 113 + NPC_VENGEFUL_SURGE = 2776 }; class npc_professor_phizzlethorpe : public CreatureScript @@ -114,7 +113,7 @@ class npc_professor_phizzlethorpe : public CreatureScript { Talk(SAY_PROGRESS_1, player); npc_escortAI::Start(false, false, player->GetGUID(), quest); - me->SetFaction(FACTION_SUNKEN_TREASURE); + me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); } } diff --git a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp index 76d0d6c702..bdb623c4f2 100644 --- a/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_ghostlands.cpp @@ -52,8 +52,7 @@ enum RangerLilatha GO_CAGE = 181152, NPC_CAPTAIN_HELIOS = 16220, NPC_MUMMIFIED_HEADHUNTER = 16342, - NPC_SHADOWPINE_ORACLE = 16343, - FACTION_QUEST_ESCAPE = 113 + NPC_SHADOWPINE_ORACLE = 16343 }; class npc_ranger_lilatha : public CreatureScript @@ -133,7 +132,7 @@ public: { if (quest->GetQuestId() == QUEST_ESCAPE_FROM_THE_CATACOMBS) { - creature->SetFaction(FACTION_QUEST_ESCAPE); + creature->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); if (npc_escortAI* pEscortAI = CAST_AI(npc_ranger_lilatha::npc_ranger_lilathaAI, creature->AI())) pEscortAI->Start(true, false, player->GetGUID()); diff --git a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp index ff3a680b15..5dea92a763 100644 --- a/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_hinterlands.cpp @@ -45,9 +45,7 @@ enum eOOX SAY_OOX_END = 4, QUEST_RESQUE_OOX_09 = 836, NPC_MARAUDING_OWL = 7808, - NPC_VILE_AMBUSHER = 7809, - FACTION_ESCORTEE_A = 774, - FACTION_ESCORTEE_H = 775 + NPC_VILE_AMBUSHER = 7809 }; class npc_oox09hl : public CreatureScript @@ -79,7 +77,7 @@ public: if (quest->GetQuestId() == QUEST_RESQUE_OOX_09) { me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetFaction(player->GetTeam() == ALLIANCE ? FACTION_ESCORTEE_A : FACTION_ESCORTEE_H); + me->SetFaction(player->GetTeam() == ALLIANCE ? FACTION_ESCORTEE_A_PASSIVE : FACTION_ESCORTEE_H_PASSIVE); Talk(SAY_OOX_START, player); npc_escortAI::Start(false, false, player->GetGUID(), quest); } diff --git a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp index 2d38b5f3d6..4fd9fa4d86 100644 --- a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp +++ b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp @@ -80,7 +80,7 @@ public: me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); me->CombatStop(); //stop combat me->DeleteThreatList(); //unsure of this - me->SetFaction(83); //horde generic + me->SetFaction(FACTION_HORDE_GENERIC); bReset = true; Reset_Timer = 60000; @@ -98,7 +98,7 @@ public: { EnterEvadeMode(); bReset = false; - me->SetFaction(28); //troll, bloodscalp + me->SetFaction(FACTION_TROLL_BLOODSCALP); return; } diff --git a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp index c5fd05924d..0647845b5f 100644 --- a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp @@ -40,7 +40,6 @@ EndContentData */ enum TapokeSlim { QUEST_MISSING_DIPLO_PT11 = 1249, - FACTION_ENEMY = 168, SPELL_STEALTH = 1785, SPELL_CALL_FRIENDS = 16457, //summons 1x friend NPC_SLIMS_FRIEND = 4971, diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp index f76c8bf6ca..3464d1b022 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -923,7 +923,7 @@ void hyjalAI::HideNearPos(float x, float y) for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) { (*itr)->SetVisible(false); - (*itr)->SetFaction(35);//make them friendly so mobs won't attack them + (*itr)->SetFaction(FACTION_FRIENDLY);//make them friendly so mobs won't attack them } } } @@ -1022,7 +1022,7 @@ void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) if ((*itr) && (*itr)->IsAlive()) { (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); - (*itr)->SetFaction(35);//make them friendly so mobs won't attack them + (*itr)->SetFaction(FACTION_FRIENDLY);//make them friendly so mobs won't attack them (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } } diff --git a/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp b/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp index f839c25291..3651419901 100644 --- a/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp +++ b/src/server/scripts/Kalimdor/Maraudon/boss_noxxion.cpp @@ -82,7 +82,7 @@ public: if (Invisible && InvisibleTimer <= diff) { //Become visible again - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); //Noxxion model me->SetDisplayId(11172); @@ -122,7 +122,7 @@ public: //Interrupt any spell casting //me->m_canMove = true; me->InterruptNonMeleeSpells(false); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); // Invisible Model me->SetDisplayId(11686); diff --git a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp index bf1b0a4598..45875f9a6e 100644 --- a/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp +++ b/src/server/scripts/Kalimdor/RazorfenDowns/razorfen_downs.cpp @@ -57,8 +57,6 @@ enum Belnistrasz EVENT_FIREBALL = 5, EVENT_FROST_NOVA = 6, - FACTION_ESCORT = 250, - PATH_ESCORT = 871710, POINT_REACH_IDOL = 17, @@ -136,7 +134,7 @@ public: eventInProgress = true; Talk(SAY_QUEST_ACCEPTED); me->RemoveFlag(UNIT_NPC_FLAGS, GOSSIP_OPTION_QUESTGIVER); - me->SetFaction(FACTION_ESCORT); + me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_ACTIVE); me->GetMotionMaster()->MovePath(PATH_ESCORT, false); } } diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp index 98d2c1d2db..08f5cc4aa9 100644 --- a/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp +++ b/src/server/scripts/Kalimdor/RazorfenKraul/instance_razorfen_kraul.cpp @@ -68,7 +68,7 @@ public: switch (go->GetEntry()) { case 21099: DoorWardGUID = go->GetGUID(); break; - case 20920: go->SetFaction(0); break; // big fat fugly hack + case 20920: go->SetFaction(FACTION_NONE); break; // big fat fugly hack } } diff --git a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp index 07f9afcd5c..bfd92dce47 100644 --- a/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp +++ b/src/server/scripts/Kalimdor/RazorfenKraul/razorfen_kraul.cpp @@ -57,7 +57,7 @@ public: { Start(true, false, player->GetGUID()); Talk(SAY_READY, player); - me->SetFaction(113); + me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); } } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp index 2627687586..2e8ee5f425 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_ouro.cpp @@ -112,7 +112,7 @@ public: //Cast me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); DoCast(me, SPELL_DIRTMOUND_PASSIVE); Submerged = true; @@ -135,7 +135,7 @@ public: if (Submerged && Back_Timer <= diff) { me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); DoCastVictim(SPELL_GROUND_RUPTURE); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index 43ca24179b..dbaee5e184 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -332,7 +332,7 @@ struct boss_twinemperorsAI : public ScriptedAI if (c->isDead()) { c->Respawn(); - c->SetFaction(7); + c->SetFaction(FACTION_CREATURE); c->RemoveAllAuras(); } if (c->IsWithinDistInMap(me, ABUSE_BUG_RANGE)) @@ -427,7 +427,7 @@ public: void CastSpellOnBug(Creature* target) override { - target->SetFaction(14); + target->SetFaction(FACTION_MONSTER); target->AI()->AttackStart(me->getThreatManager().getHostilTarget()); target->AddAura(SPELL_MUTATE_BUG, target); target->SetFullHealth(); @@ -518,7 +518,7 @@ public: void CastSpellOnBug(Creature* target) override { - target->SetFaction(14); + target->SetFaction(FACTION_MONSTER); target->AddAura(SPELL_EXPLODEBUG, target); target->SetFullHealth(); } diff --git a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp index bd77e4c954..810aa789ea 100644 --- a/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp +++ b/src/server/scripts/Kalimdor/WailingCaverns/wailing_caverns.cpp @@ -96,7 +96,7 @@ public: creature->AI()->Talk(SAY_MAKE_PREPARATIONS); - creature->SetFaction(250); + creature->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_ACTIVE); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); ENSURE_AI(npc_escortAI, (creature->AI()))->Start(false, false, player->GetGUID()); diff --git a/src/server/scripts/Kalimdor/ZulFarrak/boss_zum_rah.cpp b/src/server/scripts/Kalimdor/ZulFarrak/boss_zum_rah.cpp index 111a897d74..3bae896e0e 100644 --- a/src/server/scripts/Kalimdor/ZulFarrak/boss_zum_rah.cpp +++ b/src/server/scripts/Kalimdor/ZulFarrak/boss_zum_rah.cpp @@ -47,11 +47,6 @@ enum Events EVENT_HEALING_WAVE = 4 }; -enum Faction -{ - ZUMRAH_FRIENDLY_FACTION = 35 -}; - class boss_zum_rah : public CreatureScript { public: @@ -73,7 +68,7 @@ public: void Reset() override { - me->SetFaction(ZUMRAH_FRIENDLY_FACTION); // areatrigger sets faction to enemy + me->SetFaction(FACTION_FRIENDLY); // areatrigger sets faction to enemy Initialize(); } diff --git a/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp b/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp index 51bc5b7a94..ed166973fc 100644 --- a/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp +++ b/src/server/scripts/Kalimdor/ZulFarrak/zulfarrak.cpp @@ -38,13 +38,6 @@ EndContentData */ ## npc_sergeant_bly ######*/ -enum blyAndCrewFactions -{ - FACTION_HOSTILE = 14, - FACTION_FRIENDLY = 35, //while in cages (so the trolls won't attack them while they're caged) - FACTION_FREED = 250 //after release (so they'll be hostile towards trolls) -}; - enum blySays { SAY_1 = 0, @@ -151,7 +144,7 @@ public: Text_Timer = 5000; break; case 3: - me->SetFaction(FACTION_HOSTILE); + me->SetFaction(FACTION_MONSTER); if (Player* target = ObjectAccessor::GetPlayer(*me, PlayerGUID)) AttackStart(target); @@ -196,7 +189,7 @@ public: { if (Creature* crew = ObjectAccessor::GetCreature(*me, instance->GetGuidData(entry))) if (crew->IsAlive()) - crew->SetFaction(FACTION_HOSTILE); + crew->SetFaction(FACTION_MONSTER); } }; @@ -235,7 +228,7 @@ private: crew->SetWalk(true); crew->SetHomePosition(x, y, z, 0); crew->GetMotionMaster()->MovePoint(1, x, y, z); - crew->SetFaction(FACTION_FREED); + crew->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_ACTIVE); } } }; diff --git a/src/server/scripts/Kalimdor/zone_ashenvale.cpp b/src/server/scripts/Kalimdor/zone_ashenvale.cpp index ecd1f2e4d6..d8a8affd13 100644 --- a/src/server/scripts/Kalimdor/zone_ashenvale.cpp +++ b/src/server/scripts/Kalimdor/zone_ashenvale.cpp @@ -43,7 +43,6 @@ enum RuulSnowhoof NPC_THISTLEFUR_TOTEMIC = 3922, NPC_THISTLEFUR_PATHFINDER = 3926, QUEST_FREEDOM_TO_RUUL = 6482, - FACTION_QUEST = 113, GO_CAGE = 178147 }; @@ -83,7 +82,7 @@ public: { if (quest->GetQuestId() == QUEST_FREEDOM_TO_RUUL) { - me->SetFaction(FACTION_QUEST); + me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); npc_escortAI::Start(true, false, player->GetGUID()); } } @@ -226,7 +225,7 @@ public: if (quest->GetQuestId() == QUEST_VORSHA) { Talk(SAY_MUG_START1); - me->SetFaction(FACTION_QUEST); + me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); npc_escortAI::Start(true, false, player->GetGUID()); } } diff --git a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp index e0bb4c1410..88f5185bb8 100644 --- a/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_azuremyst_isle.cpp @@ -187,7 +187,6 @@ enum Overgrind AREA_COVE = 3579, AREA_ISLE = 3639, QUEST_GNOMERCY = 9537, - FACTION_HOSTILE = 14, SPELL_DYNAMITE = 7978 }; @@ -232,7 +231,7 @@ public: void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 /*gossipListId*/) override { CloseGossipMenuFor(player); - me->SetFaction(FACTION_HOSTILE); + me->SetFaction(FACTION_MONSTER); me->Attack(player, true); } @@ -337,8 +336,7 @@ enum Magwin EVENT_STAND = 3, EVENT_TALK_END = 4, EVENT_COWLEN_TALK = 5, - QUEST_A_CRY_FOR_HELP = 9528, - FACTION_QUEST = 113 + QUEST_A_CRY_FOR_HELP = 9528 }; class npc_magwin : public CreatureScript @@ -403,7 +401,7 @@ public: case EVENT_ACCEPT_QUEST: if (Player* player = ObjectAccessor::GetPlayer(*me, _player)) Talk(SAY_START, player); - me->SetFaction(FACTION_QUEST); + me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); _events.ScheduleEvent(EVENT_START_ESCORT, Seconds(1)); break; case EVENT_START_ESCORT: diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp index c07078a017..25e78a79c7 100644 --- a/src/server/scripts/Kalimdor/zone_silithus.cpp +++ b/src/server/scripts/Kalimdor/zone_silithus.cpp @@ -42,9 +42,6 @@ enum EternalBoard { QUEST_A_PAWN_ON_THE_ETERNAL_BOARD = 8519, - FACTION_HOSTILE = 14, - FACTION_FRIENDLY = 35, - EVENT_AREA_RADIUS = 65, // 65yds EVENT_COOLDOWN = 500000, // in ms. appears after event completed or failed (should be = Adds despawn time) @@ -970,7 +967,7 @@ public: Merithra->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); Merithra->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); Merithra->SetUInt32Value(UNIT_FIELD_DISPLAYID, MERITHRA_NIGHT_ELF_FORM); - Merithra->SetFaction(35); + Merithra->SetFaction(FACTION_FRIENDLY); } if (Caelestrasz) @@ -978,7 +975,7 @@ public: Caelestrasz->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); Caelestrasz->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); Caelestrasz->SetUInt32Value(UNIT_FIELD_DISPLAYID, CAELESTRASZ_NIGHT_ELF_FORM); - Caelestrasz->SetFaction(35); + Caelestrasz->SetFaction(FACTION_FRIENDLY); } if (Arygos) @@ -986,7 +983,7 @@ public: Arygos->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); Arygos->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); Arygos->SetUInt32Value(UNIT_FIELD_DISPLAYID, ARYGOS_GNOME_FORM); - Arygos->SetFaction(35); + Arygos->SetFaction(FACTION_FRIENDLY); } if (Anachronos) diff --git a/src/server/scripts/Kalimdor/zone_tanaris.cpp b/src/server/scripts/Kalimdor/zone_tanaris.cpp index fdc4cef041..e05ab14c16 100644 --- a/src/server/scripts/Kalimdor/zone_tanaris.cpp +++ b/src/server/scripts/Kalimdor/zone_tanaris.cpp @@ -91,7 +91,7 @@ public: void Reset() override { Initialize(); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); } void SendItem(Unit* receiver) @@ -121,7 +121,7 @@ public: { if (SwitchFactionTimer <= diff) { - me->SetFaction(91); + me->SetFaction(FACTION_ELEMENTAL); isFriendly = false; } else SwitchFactionTimer -= diff; } @@ -319,7 +319,7 @@ public: { if (quest->GetQuestId() == Q_OOX17) { - creature->SetFaction(113); + creature->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); creature->SetFullHealth(); creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); diff --git a/src/server/scripts/Kalimdor/zone_winterspring.cpp b/src/server/scripts/Kalimdor/zone_winterspring.cpp index e16fb9bd0a..ae1dc4206f 100644 --- a/src/server/scripts/Kalimdor/zone_winterspring.cpp +++ b/src/server/scripts/Kalimdor/zone_winterspring.cpp @@ -297,7 +297,7 @@ public: if (quest->GetQuestId() == QUEST_GUARDIANS_ALTAR) { creature->AI()->Talk(SAY_QUEST_START); - creature->SetFaction(FACTION_ESCORT_A_NEUTRAL_PASSIVE); + creature->SetFaction(FACTION_ESCORTEE_A_NEUTRAL_PASSIVE); if (npc_ranshallaAI* escortAI = dynamic_cast(creature->AI())) escortAI->Start(false, false, player->GetGUID(), quest); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp index ad61b20cf3..0b6c7738cc 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp @@ -192,7 +192,7 @@ public: { damage = 0; EnterEvadeMode(); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); bDone = true; } } @@ -320,7 +320,7 @@ public: { damage = 0; EnterEvadeMode(); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); bDone = true; } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index c315080327..5e9d6515db 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -224,7 +224,7 @@ class boss_anubarak_trial : public CreatureScript for (int i = 0; i < 10; i++) if (Creature* scarab = me->SummonCreature(NPC_SCARAB, AnubarakLoc[1].GetPositionX()+urand(0, 50)-25, AnubarakLoc[1].GetPositionY()+urand(0, 50)-25, AnubarakLoc[1].GetPositionZ())) { - scarab->SetFaction(31); + scarab->SetFaction(FACTION_PREY); scarab->GetMotionMaster()->MoveRandom(10); } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 5c102bcaeb..2e074d8c73 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -202,7 +202,6 @@ enum Actions enum Misc { DATA_MADE_A_MESS = 45374613, // 4537, 4613 are achievement IDs - FACTION_SCOURGE = 974, GOSSIP_MENU_MURADIN_BRONZEBEARD = 10934, GOSSIP_MENU_HIGH_OVERLORD_SAURFANG = 10952 @@ -461,7 +460,7 @@ class boss_deathbringer_saurfang : public CreatureScript { case EVENT_INTRO_ALLIANCE_2: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(FACTION_SCOURGE); + me->SetFaction(FACTION_UNDEAD_SCOURGE); Talk(SAY_INTRO_ALLIANCE_2); break; case EVENT_INTRO_ALLIANCE_3: @@ -474,7 +473,7 @@ class boss_deathbringer_saurfang : public CreatureScript break; case EVENT_INTRO_HORDE_2: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(FACTION_SCOURGE); + me->SetFaction(FACTION_UNDEAD_SCOURGE); Talk(SAY_INTRO_HORDE_2); break; case EVENT_INTRO_HORDE_4: diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index 4c306d937c..dad8012106 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -53,62 +53,68 @@ enum ScriptTexts enum Spells { // Lady Deathwhisper - SPELL_MANA_BARRIER = 70842, - SPELL_SHADOW_BOLT = 71254, - SPELL_DEATH_AND_DECAY = 71001, - SPELL_DOMINATE_MIND = 71289, - SPELL_DOMINATE_MIND_SCALE = 71290, - SPELL_FROSTBOLT = 71420, - SPELL_FROSTBOLT_VOLLEY = 72905, - SPELL_TOUCH_OF_INSIGNIFICANCE = 71204, - SPELL_SUMMON_SHADE = 71363, - SPELL_SHADOW_CHANNELING = 43897, - SPELL_DARK_TRANSFORMATION_T = 70895, - SPELL_DARK_EMPOWERMENT_T = 70896, - SPELL_DARK_MARTYRDOM_T = 70897, - SPELL_SUMMON_SPIRITS = 72478, + SPELL_MANA_BARRIER = 70842, + SPELL_SHADOW_BOLT = 71254, + SPELL_DEATH_AND_DECAY = 71001, + SPELL_DOMINATE_MIND = 71289, + SPELL_DOMINATE_MIND_SCALE = 71290, + SPELL_FROSTBOLT = 71420, + SPELL_FROSTBOLT_VOLLEY = 72905, + SPELL_TOUCH_OF_INSIGNIFICANCE = 71204, + SPELL_SUMMON_SHADE = 71363, + SPELL_SHADOW_CHANNELING = 43897, + SPELL_DARK_TRANSFORMATION_T = 70895, + SPELL_DARK_EMPOWERMENT_T = 70896, + SPELL_DARK_MARTYRDOM_T = 70897, + SPELL_SUMMON_SPIRITS = 72478, // Achievement - SPELL_FULL_HOUSE = 72827, // does not exist in dbc but still can be used for criteria check + SPELL_FULL_HOUSE = 72827, // does not exist in dbc but still can be used for criteria check // Both Adds - SPELL_TELEPORT_VISUAL = 41236, - SPELL_CLEAR_ALL_DEBUFFS = 34098, - SPELL_FULL_HEAL = 17683, - SPELL_PERMANENT_FEIGN_DEATH = 70628, + SPELL_TELEPORT_VISUAL = 41236, + SPELL_CLEAR_ALL_DEBUFFS = 34098, + SPELL_FULL_HEAL = 17683, + SPELL_PERMANENT_FEIGN_DEATH = 70628, // Fanatics - SPELL_DARK_TRANSFORMATION = 70900, - SPELL_NECROTIC_STRIKE = 70659, - SPELL_SHADOW_CLEAVE = 70670, - SPELL_VAMPIRIC_MIGHT = 70674, - SPELL_FANATIC_S_DETERMINATION = 71235, - SPELL_DARK_MARTYRDOM_FANATIC = 71236, + SPELL_DARK_TRANSFORMATION = 70900, + SPELL_NECROTIC_STRIKE = 70659, + SPELL_SHADOW_CLEAVE = 70670, + SPELL_VAMPIRIC_MIGHT = 70674, + SPELL_FANATIC_S_DETERMINATION = 71235, + SPELL_DARK_MARTYRDOM_FANATIC = 71236, + SPELL_DARK_MARTYRDOM_FANATIC_25N = 72495, + SPELL_DARK_MARTYRDOM_FANATIC_10H = 72496, + SPELL_DARK_MARTYRDOM_FANATIC_25H = 72497, // Adherents - SPELL_DARK_EMPOWERMENT = 70901, - SPELL_FROST_FEVER = 67767, - SPELL_DEATHCHILL_BOLT = 70594, - SPELL_DEATHCHILL_BLAST = 70906, - SPELL_CURSE_OF_TORPOR = 71237, - SPELL_SHROUD_OF_THE_OCCULT = 70768, - SPELL_ADHERENT_S_DETERMINATION = 71234, - SPELL_DARK_MARTYRDOM_ADHERENT = 70903, + SPELL_DARK_EMPOWERMENT = 70901, + SPELL_FROST_FEVER = 67767, + SPELL_DEATHCHILL_BOLT = 70594, + SPELL_DEATHCHILL_BLAST = 70906, + SPELL_CURSE_OF_TORPOR = 71237, + SPELL_SHROUD_OF_THE_OCCULT = 70768, + SPELL_ADHERENT_S_DETERMINATION = 71234, + SPELL_DARK_MARTYRDOM_ADHERENT = 70903, + SPELL_DARK_MARTYRDOM_ADHERENT_25N = 72498, + SPELL_DARK_MARTYRDOM_ADHERENT_10H = 72499, + SPELL_DARK_MARTYRDOM_ADHERENT_25H = 72500, // Vengeful Shade - SPELL_VENGEFUL_BLAST = 71544, - SPELL_VENGEFUL_BLAST_PASSIVE = 71494, - SPELL_VENGEFUL_BLAST_25N = 72010, - SPELL_VENGEFUL_BLAST_10H = 72011, - SPELL_VENGEFUL_BLAST_25H = 72012, + SPELL_VENGEFUL_BLAST = 71544, + SPELL_VENGEFUL_BLAST_PASSIVE = 71494, + SPELL_VENGEFUL_BLAST_25N = 72010, + SPELL_VENGEFUL_BLAST_10H = 72011, + SPELL_VENGEFUL_BLAST_25H = 72012, // Darnavan - SPELL_BLADESTORM = 65947, - SPELL_CHARGE = 65927, - SPELL_INTIMIDATING_SHOUT = 65930, - SPELL_MORTAL_STRIKE = 65926, - SPELL_SHATTERING_THROW = 65940, - SPELL_SUNDER_ARMOR = 65936, + SPELL_BLADESTORM = 65947, + SPELL_CHARGE = 65927, + SPELL_INTIMIDATING_SHOUT = 65930, + SPELL_MORTAL_STRIKE = 65926, + SPELL_SHATTERING_THROW = 65940, + SPELL_SUNDER_ARMOR = 65936, }; enum EventTypes @@ -355,7 +361,7 @@ class boss_lady_deathwhisper : public CreatureScript { if (darnavan->IsAlive()) { - darnavan->SetFaction(35); + darnavan->SetFaction(FACTION_FRIENDLY); darnavan->CombatStop(true); darnavan->GetMotionMaster()->MoveIdle(); darnavan->SetReactState(REACT_PASSIVE); @@ -636,6 +642,9 @@ class npc_cult_fanatic : public CreatureScript DoCastSelf(SPELL_DARK_MARTYRDOM_FANATIC); break; case SPELL_DARK_MARTYRDOM_FANATIC: + case SPELL_DARK_MARTYRDOM_FANATIC_25N: + case SPELL_DARK_MARTYRDOM_FANATIC_10H: + case SPELL_DARK_MARTYRDOM_FANATIC_25H: _scheduler .Schedule(Seconds(2), [this](TaskContext /*context*/) { @@ -735,6 +744,9 @@ class npc_cult_adherent : public CreatureScript DoCastSelf(SPELL_DARK_MARTYRDOM_ADHERENT); break; case SPELL_DARK_MARTYRDOM_ADHERENT: + case SPELL_DARK_MARTYRDOM_ADHERENT_25N: + case SPELL_DARK_MARTYRDOM_ADHERENT_10H: + case SPELL_DARK_MARTYRDOM_ADHERENT_25H: _scheduler .Schedule(Seconds(2), [this](TaskContext /*context*/) { diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index ce6bcb0a39..5deb7fc515 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -170,12 +170,6 @@ enum Seats SEAT_0 = 0 }; -enum Factions -{ - // Needed for melee hover disks /when Nexus Lords die/ - FACTION_FRIENDLY = 35 -}; - enum Actions { // Malygos diff --git a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp index 4ae82a8927..dcb1886e81 100644 --- a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp +++ b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp @@ -21,11 +21,6 @@ #include "Player.h" #include "nexus.h" -enum Factions -{ - FACTION_HOSTILE_FOR_ALL = 16 -}; - class instance_nexus : public InstanceMapScript { public: @@ -59,31 +54,31 @@ class instance_nexus : public InstanceMapScript // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. case NPC_ALLIANCE_BERSERKER: if (ServerAllowsTwoSideGroups()) - creature->SetFaction(FACTION_HOSTILE_FOR_ALL); + creature->SetFaction(FACTION_MONSTER_2); if (_teamInInstance == ALLIANCE) creature->UpdateEntry(NPC_HORDE_BERSERKER); break; case NPC_ALLIANCE_RANGER: if (ServerAllowsTwoSideGroups()) - creature->SetFaction(FACTION_HOSTILE_FOR_ALL); + creature->SetFaction(FACTION_MONSTER_2); if (_teamInInstance == ALLIANCE) creature->UpdateEntry(NPC_HORDE_RANGER); break; case NPC_ALLIANCE_CLERIC: if (ServerAllowsTwoSideGroups()) - creature->SetFaction(FACTION_HOSTILE_FOR_ALL); + creature->SetFaction(FACTION_MONSTER_2); if (_teamInInstance == ALLIANCE) creature->UpdateEntry(NPC_HORDE_CLERIC); break; case NPC_ALLIANCE_COMMANDER: if (ServerAllowsTwoSideGroups()) - creature->SetFaction(FACTION_HOSTILE_FOR_ALL); + creature->SetFaction(FACTION_MONSTER_2); if (_teamInInstance == ALLIANCE) creature->UpdateEntry(NPC_HORDE_COMMANDER); break; case NPC_COMMANDER_STOUTBEARD: if (ServerAllowsTwoSideGroups()) - creature->SetFaction(FACTION_HOSTILE_FOR_ALL); + creature->SetFaction(FACTION_MONSTER_2); if (_teamInInstance == ALLIANCE) creature->UpdateEntry(NPC_COMMANDER_KOLURG); break; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp index 12fb89bb12..e0b7634173 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp @@ -531,7 +531,7 @@ class boss_algalon_the_observer : public CreatureScript damage = 0; me->SetReactState(REACT_PASSIVE); me->AttackStop(); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_SELF_STUN); events.Reset(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index 24d3a54f07..8a0be11c31 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -222,7 +222,7 @@ class npc_iron_roots : public CreatureScript SetCombatMovement(false); me->ApplySpellImmune(0, IMMUNITY_ID, 49560, true); // Death Grip - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); me->SetReactState(REACT_PASSIVE); } @@ -606,7 +606,7 @@ class boss_freya : public CreatureScript _JustDied(); me->RemoveAllAuras(); me->AttackStop(); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->DeleteThreatList(); me->CombatStop(true); me->DespawnOrUnsummon(7500); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index 2d41216263..8c6f9fc94f 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -405,7 +405,7 @@ class boss_hodir : public CreatureScript DoCastAOE(SPELL_KILL_CREDIT, true); /// need to be cast before changing boss faction /// spell will target enemies only - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->DespawnOrUnsummon(10000); _JustDied(); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp index 5c42276e63..7aa60e8af6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp @@ -177,7 +177,7 @@ class boss_ignis : public CreatureScript { if (summon->GetEntry() == NPC_IRON_CONSTRUCT) { - summon->SetFaction(16); + summon->SetFaction(FACTION_MONSTER_2); summon->SetReactState(REACT_AGGRESSIVE); summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED | UNIT_FLAG_STUNNED | UNIT_FLAG_IMMUNE_TO_PC); summon->SetControlled(false, UNIT_STATE_ROOT); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 8152183231..e56de3450c 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -635,7 +635,7 @@ class boss_mimiron : public CreatureScript case EVENT_OUTTRO_1: me->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL_1); DoCast(me, SPELL_SLEEP_VISUAL_2); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); events.ScheduleEvent(EVENT_OUTTRO_2, 3000); break; case EVENT_OUTTRO_2: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index ea2fa4027a..0856f1a457 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -15,27 +15,423 @@ * with this program. If not, see . */ +#include "MoveSplineInit.h" +#include "Player.h" #include "ScriptMgr.h" #include "ScriptedCreature.h" +#include "SpellScript.h" +#include "SpellAuraEffects.h" +#include "TypeContainerVisitor.h" +#include "CellImpl.h" +#include "GridNotifiersImpl.h" #include "ulduar.h" +enum Spells +{ + // Thorim + SPELL_SHEATH_OF_LIGHTNING = 62276, + SPELL_STORMHAMMER = 62042, + SPELL_STORMHAMMER_SIF = 64767, + SPELL_STORMHAMMER_BOOMERANG = 64909, + SPELL_DEAFENING_THUNDER = 62470, + SPELL_CHARGE_ORB = 62016, + SPELL_SUMMON_LIGHTNING_ORB = 62391, + SPELL_LIGHTNING_DESTRUCTION = 62393, + SPELL_TOUCH_OF_DOMINION = 62507, + SPELL_TOUCH_OF_DOMINION_TRIGGERED = 62565, + SPELL_CHAIN_LIGHTNING = 62131, + SPELL_LIGHTNING_ORB_CHARGED = 62186, // wrong duration, triggered spell should handle lightning release + SPELL_LIGHTNING_CHARGE = 62279, + SPELL_LIGHTNING_RELEASE = 62466, + SPELL_LIGHTNING_PILLAR_2 = 62976, // caster high position, target low position + SPELL_LIGHTNING_PILLAR_1 = 63238, // caster high position, target low position + SPELL_UNBALANCING_STRIKE = 62130, + SPELL_BERSERK_PHASE_1 = 62560, + SPELL_BERSERK_PHASE_2 = 62555, + SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC = 62184, + + // Credits + SPELL_CREDIT_SIFFED = 64980, + SPELL_CREDIT_KILL = 64985, + + // Lightning Field + SPELL_LIGHTNING_FIELD = 64972, + SPELL_LIGHTNING_BEAM_CHANNEL = 45537, + + // Sif + SPELL_BLIZZARD = 62577, + SPELL_BLINK = 62578, + SPELL_FROSTBOLT_VOLLEY = 62580, + SPELL_FROSTBOLT = 62583, + SPELL_FROSTNOVA = 62597, + SPELL_SIF_TRANSFORM = 64778, + + // Runic Colossus + SPELL_SMASH = 62339, + SPELL_RUNIC_BARRIER = 62338, + SPELL_RUNIC_CHARGE = 62613, + SPELL_RUNIC_SMASH = 62465, + SPELL_RUNIC_SMASH_RIGHT = 62057, + SPELL_RUNIC_SMASH_LEFT = 62058, + + // Ancient Rune Giant + SPELL_RUNIC_FORTIFICATION = 62942, + SPELL_RUNE_DETONATION = 62526, + SPELL_STOMP = 62411 +}; + +enum Phases +{ + PHASE_NULL, + PHASE_1, + PHASE_2 +}; + +enum Events +{ + // Thorim + EVENT_SAY_AGGRO_2 = 1, + EVENT_SAY_SIF_START, + EVENT_START_SIF_CHANNEL, + EVENT_STORMHAMMER, + EVENT_CHARGE_ORB, + EVENT_SUMMON_ADDS, + EVENT_BERSERK, + EVENT_JUMPDOWN, + EVENT_UNBALANCING_STRIKE, + EVENT_CHAIN_LIGHTNING, + EVENT_START_PERIODIC_CHARGE, + EVENT_LIGHTNING_CHARGE, + EVENT_ACTIVATE_LIGHTNING_FIELD, + EVENT_OUTRO_1, + EVENT_OUTRO_2, + EVENT_OUTRO_3, + + // Runic Colossus + EVENT_RUNIC_BARRIER, + EVENT_SMASH, + EVENT_RUNIC_CHARGE, + EVENT_RUNIC_SMASH, + + // Ancient Rune Giant + EVENT_RUNIC_FORTIFICATION, + EVENT_STOMP, + EVENT_RUNE_DETONATION, + + // Arena NPC + EVENT_PRIMARY_ABILITY, + EVENT_SECONDARY_ABILITY, + EVENT_THIRD_ABILITY, + EVENT_ABILITY_CHARGE, + + // Sif + EVENT_BLINK, + EVENT_FROST_NOVA, + EVENT_FROSTBOLT, + EVENT_FROSTBOLT_VOLLEY, + EVENT_BLIZZARD +}; + enum Yells { - SAY_AGGRO = 0, - SAY_SPECIAL_1 = 1, - SAY_SPECIAL_2 = 2, - SAY_SPECIAL_3 = 3, - SAY_JUMPDOWN = 4, - SAY_SLAY = 5, - SAY_BERSERK = 6, - SAY_WIPE = 7, - SAY_DEATH = 8, - SAY_END_NORMAL_1 = 9, - SAY_END_NORMAL_2 = 10, - SAY_END_NORMAL_3 = 11, - SAY_END_HARD_1 = 12, - SAY_END_HARD_2 = 13, - SAY_END_HARD_3 = 14 + // Thorim + SAY_AGGRO_1 = 0, + SAY_AGGRO_2 = 1, + SAY_SPECIAL = 2, + SAY_JUMPDOWN = 3, + SAY_SLAY = 4, + SAY_BERSERK = 5, + SAY_WIPE = 6, + SAY_DEATH = 7, + SAY_END_NORMAL_1 = 8, + SAY_END_NORMAL_2 = 9, + SAY_END_NORMAL_3 = 10, + SAY_END_HARD_1 = 11, + SAY_END_HARD_2 = 12, + SAY_END_HARD_3 = 13, + + // Runic Colossus + EMOTE_RUNIC_BARRIER = 0, + + // Ancient Rune Giant + EMOTE_RUNIC_MIGHT = 0, + + // Sif + SAY_SIF_START = 0, + SAY_SIF_DESPAWN = 1, + SAY_SIF_EVENT = 2 +}; + +enum PreAddSpells +{ + SPELL_ACID_BREATH = 62315, + SPELL_SWEEP = 62316, + + SPELL_DEVASTATE = 62317, + SPELL_HEROIC_SWIPE = 62444, + SPELL_SUNDER_ARMOR = 57807, + + SPELL_BARBED_SHOT = 62318, + SPELL_SHOOT = 16496, + + SPELL_RENEW = 62333, + SPELL_GREATER_HEAL = 62334, /// 61965 + SPELL_CIRCLE_OF_HEALING = 61964, + + SPELL_HOLY_SMITE = 62335, + + SPELL_LEAP = 61934, + + SPELL_CHARGE = 32323, + SPELL_MORTAL_STRIKE = 35054, + SPELL_WHIRLWIND = 33500, + + SPELL_LOW_BLOW = 62326, + SPELL_PUMMEL = 38313, + + SPELL_RUNIC_LIGHTNING = 62327, + SPELL_RUNIC_MENDING = 62328, + SPELL_RUNIC_SHIELD = 62321, + + SPELL_RUNIC_STRIKE = 62322, + SPELL_AURA_OF_CELERITY = 62320, + + SPELL_IMPALE = 62331, + SPELL_WHIRLING_TRIP = 64151, + + SPELL_CLEAVE = 42724, + SPELL_HAMSTRING = 48639, + SPELL_SHIELD_SMASH = 62332, +}; + +enum TrashTypes +{ + // Pre Phase Trash + BEHEMOTH, + MERCENARY_CAPTAIN, + MERCENARY_SOLDIER, + + // Arena Phase Trash + DARK_RUNE_CHAMPION, + DARK_RUNE_WARBRINGER, + DARK_RUNE_COMMONER, + DARK_RUNE_EVOKER, + + // Hall Way Trash + IRON_RING_GUARD, + IRON_HONOR_GUARD, + + // Shared + DARK_RUNE_ACOLYTE +}; + +struct ThorimTrashInfo +{ + uint32 Type; + uint32 Entry; + uint32 PrimaryAbility; + uint32 SecondaryAbility; + uint32 ThirdAbility; +}; + +uint8 const ThorimTrashCount = 13; +ThorimTrashInfo const StaticThorimTrashInfo[ThorimTrashCount] = +{ + // Pre Phase + { BEHEMOTH, NPC_JORMUNGAR_BEHEMOTH, SPELL_ACID_BREATH, SPELL_SWEEP, 0 }, + { MERCENARY_CAPTAIN, NPC_MERCENARY_CAPTAIN_A, SPELL_DEVASTATE, SPELL_HEROIC_SWIPE, SPELL_SUNDER_ARMOR }, + { MERCENARY_SOLDIER, NPC_MERCENARY_SOLDIER_A, SPELL_BARBED_SHOT, SPELL_SHOOT, 0 }, + { DARK_RUNE_ACOLYTE, NPC_DARK_RUNE_ACOLYTE_PRE, SPELL_RENEW, SPELL_GREATER_HEAL, SPELL_CIRCLE_OF_HEALING }, + { MERCENARY_CAPTAIN, NPC_MERCENARY_CAPTAIN_H, SPELL_DEVASTATE, SPELL_HEROIC_SWIPE, SPELL_SUNDER_ARMOR }, + { MERCENARY_SOLDIER, NPC_MERCENARY_SOLDIER_H, SPELL_BARBED_SHOT, SPELL_SHOOT, 0 }, + + // Arena Phase + { DARK_RUNE_CHAMPION, NPC_DARK_RUNE_CHAMPION, SPELL_MORTAL_STRIKE, SPELL_WHIRLWIND, 0 }, + { DARK_RUNE_WARBRINGER, NPC_DARK_RUNE_WARBRINGER, SPELL_RUNIC_STRIKE, 0, 0 }, + { DARK_RUNE_EVOKER, NPC_DARK_RUNE_EVOKER, SPELL_RUNIC_LIGHTNING, SPELL_RUNIC_SHIELD, SPELL_RUNIC_MENDING }, + { DARK_RUNE_COMMONER, NPC_DARK_RUNE_COMMONER, SPELL_LOW_BLOW, SPELL_PUMMEL, 0 }, + + // Hall Way + { IRON_RING_GUARD, NPC_IRON_RING_GUARD, SPELL_WHIRLING_TRIP, SPELL_IMPALE, 0 }, + { IRON_HONOR_GUARD, NPC_IRON_HONOR_GUARD, SPELL_CLEAVE, SPELL_SHIELD_SMASH, 0 }, + { DARK_RUNE_ACOLYTE, NPC_DARK_RUNE_ACOLYTE, SPELL_RENEW, SPELL_GREATER_HEAL, 0 } +}; + +enum Actions +{ + ACTION_INCREASE_PREADDS_COUNT, + ACTION_ACTIVATE_RUNIC_SMASH, + ACTION_ACTIVATE_ADDS, + ACTION_PILLAR_CHARGED, + ACTION_START_HARD_MODE, + ACTION_BERSERK +}; + +struct SummonLocation +{ + Position pos; + uint32 entry; +}; + +SummonLocation const PreAddLocations[] = +{ + { { 2149.68f, -263.477f, 419.679f, 3.120f }, NPC_JORMUNGAR_BEHEMOTH }, + { { 2131.31f, -271.640f, 419.840f, 2.188f }, NPC_MERCENARY_CAPTAIN_A }, + { { 2127.24f, -259.182f, 419.974f, 5.917f }, NPC_MERCENARY_SOLDIER_A }, + { { 2123.32f, -254.770f, 419.840f, 6.170f }, NPC_MERCENARY_SOLDIER_A }, + { { 2120.10f, -258.990f, 419.840f, 6.250f }, NPC_MERCENARY_SOLDIER_A }, + { { 2129.09f, -277.142f, 419.756f, 1.222f }, NPC_DARK_RUNE_ACOLYTE_PRE } +}; + +SummonLocation const ColossusAddLocations[] = +{ + { { 2218.38f, -297.50f, 412.18f, 1.030f }, NPC_IRON_RING_GUARD }, + { { 2235.07f, -297.98f, 412.18f, 1.613f }, NPC_IRON_RING_GUARD }, + { { 2235.26f, -338.34f, 412.18f, 1.589f }, NPC_IRON_RING_GUARD }, + { { 2217.69f, -337.39f, 412.18f, 1.241f }, NPC_IRON_RING_GUARD }, + { { 2227.58f, -308.30f, 412.18f, 1.591f }, NPC_DARK_RUNE_ACOLYTE }, + { { 2227.47f, -345.37f, 412.18f, 1.566f }, NPC_DARK_RUNE_ACOLYTE } +}; + +SummonLocation const GiantAddLocations[] = +{ + { { 2198.05f, -428.77f, 419.95f, 6.056f }, NPC_IRON_HONOR_GUARD }, + { { 2220.31f, -436.22f, 412.26f, 1.064f }, NPC_IRON_HONOR_GUARD }, + { { 2158.88f, -441.73f, 438.25f, 0.127f }, NPC_IRON_HONOR_GUARD }, + { { 2198.29f, -436.92f, 419.95f, 0.261f }, NPC_DARK_RUNE_ACOLYTE }, + { { 2230.93f, -434.27f, 412.26f, 1.931f }, NPC_DARK_RUNE_ACOLYTE } +}; + +Position const SifSpawnPosition = { 2148.301f, -297.8453f, 438.3308f, 2.687807f }; + +enum Data +{ + ACHIEVEMENT_DONT_STAND_IN_THE_LIGHTNING = 29712972, + ACHIEVEMENT_SIFFED = 29772978, + ACHIEVEMENT_LOSE_YOUR_ILLUSION = 31763183, + DATA_CHARGED_PILLAR = 1 +}; + +enum DisplayIds +{ + THORIM_WEAPON_DISPLAY_ID = 45900 +}; + +uint32 const LightningOrbPathSize = 8; +G3D::Vector3 const LightningOrbPath[LightningOrbPathSize] = +{ + { 2134.889893f, -298.632996f, 438.247467f }, + { 2134.570068f, -440.317993f, 438.247467f }, + { 2167.820312f, -440.330261f, 438.247589f }, + { 2213.394287f, -433.318298f, 412.665863f }, + { 2227.766113f, -433.275818f, 412.177032f }, + { 2227.551270f, -263.081085f, 412.176880f }, + { 2202.208008f, -262.939270f, 412.168976f }, + { 2182.310059f, -263.233093f, 414.739410f } +}; + +// used for trash jump calculation +Position const ArenaCenter = { 2134.77f, -262.307f }; + +// used for lightning field calculation +Position const LightningFieldCenter = { 2135.178f, -321.122f }; + +CircleBoundary const ArenaFloorCircle(ArenaCenter, 45.4); +CircleBoundary const InvertedBalconyCircle(LightningFieldCenter, 32.0, true); + +CreatureBoundary const ArenaBoundaries = +{ + &ArenaFloorCircle, + &InvertedBalconyCircle +}; + +class HeightPositionCheck +{ + public: + HeightPositionCheck(bool ret) : _ret(ret) { } + + bool operator()(Position const* pos) const + { + return pos->GetPositionZ() > THORIM_BALCONY_Z_CHECK == _ret; + } + + private: + bool _ret; + + static float const THORIM_BALCONY_Z_CHECK; +}; +float const HeightPositionCheck::THORIM_BALCONY_Z_CHECK = 428.0f; + +class RunicSmashExplosionEvent : public BasicEvent +{ + public: + RunicSmashExplosionEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override + { + _owner->CastSpell((Unit*)nullptr, SPELL_RUNIC_SMASH); + return true; + } + + private: + Creature* _owner; +}; + +class TrashJumpEvent : public BasicEvent +{ + public: + TrashJumpEvent(Creature* owner) : _owner(owner), _stage(0) { } + + bool Execute(uint64 eventTime, uint32 /*updateTime*/) override + { + switch (_stage) + { + case 0: + _owner->CastSpell((Unit*)nullptr, SPELL_LEAP); + ++_stage; + _owner->m_Events.AddEvent(this, eventTime + 2000); + return false; + case 1: + _owner->SetReactState(REACT_AGGRESSIVE); + _owner->AI()->DoZoneInCombat(_owner); + _owner->AI()->SetBoundary(&ArenaBoundaries); + return true; + default: + break; + } + + return true; + } + + private: + Creature* _owner; + uint8 _stage; +}; + +class LightningFieldEvent : public BasicEvent +{ + public: + LightningFieldEvent(Creature* owner) : _owner(owner) { } + + bool Execute(uint64 eventTime, uint32 /*updateTime*/) override + { + if (InstanceScript* instance = _owner->GetInstanceScript()) + { + if (instance->GetBossState(BOSS_THORIM) == IN_PROGRESS) + { + _owner->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_FIELD); + _owner->m_Events.AddEvent(this, eventTime + 1000); + return false; + } + } + + _owner->InterruptNonMeleeSpells(false); + _owner->AI()->EnterEvadeMode(); + return true; + } + + private: + Creature* _owner; }; class boss_thorim : public CreatureScript @@ -47,17 +443,92 @@ class boss_thorim : public CreatureScript { boss_thorimAI(Creature* creature) : BossAI(creature, BOSS_THORIM) { + _encounterFinished = false; + Initialize(); + } + + void Initialize() + { + _killedCount = 0; + _waveType = 0; + _hardMode = true; + _orbSummoned = false; + _dontStandInTheLightning = true; } void Reset() override { + if (_encounterFinished) + return; + + SetBoundary(nullptr); _Reset(); + Initialize(); + + me->SetReactState(REACT_PASSIVE); + me->SetDisableGravity(true); + me->SetControlled(true, UNIT_STATE_ROOT); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + + events.SetPhase(PHASE_NULL); + + // Respawn Mini Bosses + for (uint8 i = DATA_RUNIC_COLOSSUS; i <= DATA_RUNE_GIANT; ++i) + if (Creature* miniBoss = ObjectAccessor::GetCreature(*me, instance->GetGuidData(i))) + miniBoss->Respawn(true); + + // Spawn Pre Phase Adds + for (SummonLocation const& s : PreAddLocations) + me->SummonCreature(s.entry, s.pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + + if (GameObject* lever = instance->GetGameObject(DATA_THORIM_LEVER)) + lever->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + // Remove trigger auras + if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID)) + pillar->RemoveAllAuras(); + + if (Creature* controller = instance->GetCreature(DATA_THORIM_CONTROLLER)) + controller->RemoveAllAuras(); + + _activePillarGUID.Clear(); } - void EnterEvadeMode(EvadeReason why) override + void EnterEvadeMode(EvadeReason /*why*/) override { - Talk(SAY_WIPE); - _EnterEvadeMode(why); + summons.DespawnAll(); + _DespawnAtEvade(); + } + + void SetGUID(ObjectGuid guid, int32 type) override + { + if (type == DATA_CHARGED_PILLAR) + { + _activePillarGUID = guid; + + if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID)) + { + pillar->CastSpell(pillar, SPELL_LIGHTNING_ORB_CHARGED, true); + pillar->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_PILLAR_2); + events.ScheduleEvent(EVENT_LIGHTNING_CHARGE, 8000, 0, PHASE_2); + } + } + } + + uint32 GetData(uint32 type) const override + { + switch (type) + { + case ACHIEVEMENT_DONT_STAND_IN_THE_LIGHTNING: + return _dontStandInTheLightning ? 1 : 0; + case ACHIEVEMENT_LOSE_YOUR_ILLUSION: + case DATA_THORIM_HARDMODE: + return _hardMode ? 1 : 0; + default: + break; + } + + return 0; } void KilledUnit(Unit* who) override @@ -66,27 +537,410 @@ class boss_thorim : public CreatureScript Talk(SAY_SLAY); } - void JustDied(Unit* /*killer*/) override + void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override { - Talk(SAY_DEATH); + if (spellInfo->Id == SPELL_TOUCH_OF_DOMINION_TRIGGERED) + { + if (Creature* sif = instance->GetCreature(DATA_SIF)) + { + sif->AI()->Talk(SAY_SIF_DESPAWN); + sif->DespawnOrUnsummon(6000); + _hardMode = false; + } + } + } + + void SpellHitTarget(Unit* who, SpellInfo const* spellInfo) override + { + if (who->GetTypeId() == TYPEID_PLAYER && spellInfo->Id == SPELL_LIGHTNING_RELEASE) + _dontStandInTheLightning = false; + } + + void FinishEncounter() + { + if (_encounterFinished) + return; + + _encounterFinished = true; + + DoCastAOE(SPELL_CREDIT_KILL, true); // before change faction + + me->SetReactState(REACT_PASSIVE); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAttackers(); + me->AttackStop(); + me->SetFaction(FACTION_FRIENDLY); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_RENAME); + + if (Creature* controller = instance->GetCreature(DATA_THORIM_CONTROLLER)) + controller->RemoveAllAuras(); + if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID)) + pillar->RemoveAllAuras(); + + if (_hardMode) + { + if (Creature* sif = instance->GetCreature(DATA_SIF)) + { + summons.Despawn(sif); + sif->DespawnOrUnsummon(10000); + } + } + _JustDied(); + + Talk(SAY_DEATH); + events.ScheduleEvent(EVENT_OUTRO_1, 4000); + events.ScheduleEvent(EVENT_OUTRO_2, _hardMode ? 8000 : 11000); + events.ScheduleEvent(EVENT_OUTRO_3, _hardMode ? 19000 : 21000); + + me->m_Events.AddEvent(new KeeperDespawnEvent(me), me->m_Events.CalculateTime(35000)); + } + + void MovementInform(uint32 type, uint32 id) override + { + if (type != EFFECT_MOTION_TYPE || id != EVENT_JUMP) + return; + + me->getThreatManager().resetAllAggro(); + SetBoundary(&ArenaBoundaries); } void EnterCombat(Unit* /*who*/) override { - Talk(SAY_AGGRO); _EnterCombat(); + Talk(SAY_AGGRO_1); + + events.SetPhase(PHASE_1); + + events.ScheduleEvent(EVENT_SAY_AGGRO_2, 9000, 0, PHASE_1); + events.ScheduleEvent(EVENT_SAY_SIF_START, 16500, 0, PHASE_1); + events.ScheduleEvent(EVENT_START_SIF_CHANNEL, 22500, 0, PHASE_1); + + events.ScheduleEvent(EVENT_STORMHAMMER, 40000, 0, PHASE_1); + events.ScheduleEvent(EVENT_CHARGE_ORB, 30000, 0, PHASE_1); + events.ScheduleEvent(EVENT_SUMMON_ADDS, 15000, 0, PHASE_1); + events.ScheduleEvent(EVENT_BERSERK, 369000); + + DoCast(me, SPELL_SHEATH_OF_LIGHTNING); + + if (Creature* runicColossus = instance->GetCreature(DATA_RUNIC_COLOSSUS)) + { + runicColossus->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + runicColossus->AI()->DoAction(ACTION_ACTIVATE_ADDS); + } + + if (GameObject* lever = instance->GetGameObject(DATA_THORIM_LEVER)) + lever->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE); + + // Summon Sif + me->SummonCreature(NPC_SIF, SifSpawnPosition); } - void UpdateAI(uint32 /*diff*/) override + void JustSummoned(Creature* summon) override + { + switch (summon->GetEntry()) + { + case NPC_LIGHTNING_ORB: + { + summon->SetReactState(REACT_PASSIVE); + summon->CastSpell(summon, SPELL_LIGHTNING_DESTRUCTION, true); + + summon->GetMotionMaster()->MovePoint(EVENT_CHARGE_PREPATH, LightningOrbPath[LightningOrbPathSize - 1], false); + + Movement::PointsArray path(LightningOrbPath, LightningOrbPath + LightningOrbPathSize); + + Movement::MoveSplineInit init(summon); + init.MovebyPath(path); + init.Launch(); + break; + } + case NPC_DARK_RUNE_CHAMPION: + case NPC_DARK_RUNE_WARBRINGER: + case NPC_DARK_RUNE_EVOKER: + case NPC_DARK_RUNE_COMMONER: + summon->SetReactState(REACT_PASSIVE); + summon->m_Events.AddEvent(new TrashJumpEvent(summon), summon->m_Events.CalculateTime(3000)); + break; + case NPC_SIF: + summon->SetReactState(REACT_PASSIVE); + break; + default: + break; + } + + BossAI::JustSummoned(summon); + } + + void UpdateAI(uint32 diff) override { if (!UpdateVictim()) return; - //SPELLS @todo - // + events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_SAY_AGGRO_2: + Talk(SAY_AGGRO_2); + break; + case EVENT_SAY_SIF_START: + if (Creature* sif = instance->GetCreature(DATA_SIF)) + sif->AI()->Talk(SAY_SIF_START); + break; + case EVENT_START_SIF_CHANNEL: + if (Creature* sif = instance->GetCreature(DATA_SIF)) + sif->CastSpell(me, SPELL_TOUCH_OF_DOMINION); + break; + case EVENT_STORMHAMMER: + DoCast(SPELL_STORMHAMMER); + events.Repeat(15000, 20000); + break; + case EVENT_CHARGE_ORB: + DoCastAOE(SPELL_CHARGE_ORB); + events.Repeat(15000, 20000); + break; + case EVENT_SUMMON_ADDS: + SummonWave(); + events.Repeat(_orbSummoned ? 3000 : 10000); + break; + case EVENT_JUMPDOWN: + if (_hardMode) + if (Creature* sif = instance->GetCreature(DATA_SIF)) + sif->AI()->DoAction(ACTION_START_HARD_MODE); + me->RemoveAurasDueToSpell(SPELL_SHEATH_OF_LIGHTNING); + me->SetReactState(REACT_AGGRESSIVE); + me->SetDisableGravity(false); + me->SetControlled(false, UNIT_STATE_ROOT); + me->GetMotionMaster()->MoveJump(2134.8f, -263.056f, 419.983f, me->GetOrientation(), 30.0f, 20.0f); + events.ScheduleEvent(EVENT_START_PERIODIC_CHARGE, 2000, 0, PHASE_2); + events.ScheduleEvent(EVENT_UNBALANCING_STRIKE, 15000, 0, PHASE_2); + events.ScheduleEvent(EVENT_CHAIN_LIGHTNING, 20000, 0, PHASE_2); + break; + case EVENT_UNBALANCING_STRIKE: + DoCastVictim(SPELL_UNBALANCING_STRIKE); + events.Repeat(15000, 20000); + break; + case EVENT_CHAIN_LIGHTNING: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_CHAIN_LIGHTNING); + events.Repeat(7000, 15000); + break; + case EVENT_START_PERIODIC_CHARGE: + if (Creature* controller = instance->GetCreature(DATA_THORIM_CONTROLLER)) + controller->CastSpell(controller, SPELL_ACTIVATE_LIGHTNING_ORB_PERIODIC, true); + break; + case EVENT_LIGHTNING_CHARGE: + if (Creature* pillar = ObjectAccessor::GetCreature(*me, _activePillarGUID)) + DoCast(pillar, SPELL_LIGHTNING_RELEASE); + break; + case EVENT_BERSERK: + if (events.IsInPhase(PHASE_1)) + { + Talk(SAY_WIPE); + DoCastAOE(SPELL_BERSERK_PHASE_1, true); + DoCast(me, SPELL_SUMMON_LIGHTNING_ORB, true); + } + else + { + Talk(SAY_BERSERK); + DoCast(me, SPELL_BERSERK_PHASE_2, true); + } + break; + case EVENT_ACTIVATE_LIGHTNING_FIELD: + { + std::list triggers; + me->GetCreatureListWithEntryInGrid(triggers, NPC_THORIM_EVENT_BUNNY, 100.0f); + triggers.remove_if([](Creature* bunny) + { + if (HeightPositionCheck(false)(bunny)) + return true; + return LightningFieldCenter.GetExactDist2dSq(bunny) > 1296.0f; + }); + + uint64 timer = 1000; + for (Creature* bunny : triggers) + bunny->m_Events.AddEvent(new LightningFieldEvent(bunny), bunny->m_Events.CalculateTime(timer += 100)); + + triggers.remove_if([](Creature* bunny) + { + return LightningFieldCenter.GetExactDist2dSq(bunny) < 576.0f; + }); + + triggers.sort([](Creature* a, Creature* b) + { + return a->GetPositionX() < b->GetPositionX(); + }); + + for (auto itr = triggers.cbegin(); itr != triggers.cend();) + { + auto prev = itr++; + if (itr != triggers.end()) + (*prev)->CastSpell(*itr, SPELL_LIGHTNING_BEAM_CHANNEL); + } + break; + } + case EVENT_OUTRO_1: + Talk(_hardMode ? SAY_END_HARD_1 : SAY_END_NORMAL_1); + if (_hardMode) + DoCast(me, SPELL_STORMHAMMER_SIF); + break; + case EVENT_OUTRO_2: + Talk(_hardMode ? SAY_END_HARD_2 : SAY_END_NORMAL_2); + if (_hardMode) + if (Creature* sif = instance->GetCreature(DATA_SIF)) + sif->SetStandState(UNIT_STAND_STATE_DEAD); + break; + case EVENT_OUTRO_3: + Talk(_hardMode ? SAY_END_HARD_3 : SAY_END_NORMAL_3); + break; + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + DoMeleeAttackIfReady(); } + + void DoAction(int32 action) override + { + switch (action) + { + case ACTION_BERSERK: + if (events.IsInPhase(PHASE_2)) + return; + + if (!_orbSummoned) + { + _orbSummoned = true; + events.RescheduleEvent(EVENT_BERSERK, 1000); + } + return; + case ACTION_INCREASE_PREADDS_COUNT: + if (++_killedCount >= 6) + { + // Event starts + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + DoZoneInCombat(me); + } + break; + default: + break; + } + } + + void GetTrashSpawnTriggers(std::list& triggerList, uint32 count = 1) + { + me->GetCreatureListWithEntryInGrid(triggerList, NPC_THORIM_EVENT_BUNNY, 100.0f); + triggerList.remove_if([](Creature* bunny) + { + if (HeightPositionCheck(false)(bunny)) + return true; + return ArenaCenter.GetExactDist2dSq(bunny) < 3025.0f; + }); + + if (triggerList.empty()) + return; + + if (count == 1) + { + Creature* bunny = Trinity::Containers::SelectRandomContainerElement(triggerList); + triggerList.clear(); + triggerList.push_back(bunny); + } + else + Trinity::Containers::RandomResizeList(triggerList, count); + } + + void SummonWave() + { + switch (_waveType) + { + case 0: + { + // Dark Rune Commoner + std::list triggers; + GetTrashSpawnTriggers(triggers, urand(5, 6)); + + for (Creature* bunny : triggers) + me->SummonCreature(StaticThorimTrashInfo[6 + 3].Entry, *bunny, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + + ++_waveType; + break; + } + case 1: + if (urand(0, 1)) + { + // Dark Rune Champion or Dark Rune Evoker + std::list triggers; + GetTrashSpawnTriggers(triggers, urand(2, 4)); + + for (Creature* bunny : triggers) + me->SummonCreature(StaticThorimTrashInfo[6 + RAND(0, 2)].Entry, *bunny, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + } + else + { + // Dark Rune Warbringer + std::list triggers; + GetTrashSpawnTriggers(triggers); + + for (Creature* bunny : triggers) + me->SummonCreature(StaticThorimTrashInfo[6 + 1].Entry, *bunny, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + } + --_waveType; + break; + } + } + + bool CanStartPhase2(Unit* actor) const + { + if (actor->GetTypeId() != TYPEID_PLAYER || !me->IsWithinDistInMap(actor, 10.0f)) + return false; + + Creature* runicColossus = instance->GetCreature(DATA_RUNIC_COLOSSUS); + Creature* runeGiant = instance->GetCreature(DATA_RUNE_GIANT); + return runicColossus && !runicColossus->IsAlive() && runeGiant && !runeGiant->IsAlive(); + } + + void DamageTaken(Unit* attacker, uint32& damage) override + { + if (events.IsInPhase(PHASE_1) && CanStartPhase2(attacker)) + { + Talk(SAY_JUMPDOWN); + events.SetPhase(PHASE_2); + events.ScheduleEvent(EVENT_JUMPDOWN, 8000); + events.ScheduleEvent(EVENT_ACTIVATE_LIGHTNING_FIELD, 15000); + events.RescheduleEvent(EVENT_BERSERK, 300000, 0, PHASE_2); + + if (Creature* sif = instance->GetCreature(DATA_SIF)) + sif->InterruptNonMeleeSpells(false); + + // Hard Mode + if (_hardMode) + DoCastAOE(SPELL_CREDIT_SIFFED, true); + } + else if (me->HealthBelowPctDamaged(1, damage)) + { + damage = 0; + FinishEncounter(); + } + } + + private: + ObjectGuid _activePillarGUID; + uint8 _killedCount; + uint8 _waveType; + bool _hardMode; + bool _encounterFinished; + bool _orbSummoned; + bool _dontStandInTheLightning; }; CreatureAI* GetAI(Creature* creature) const override @@ -95,7 +949,1274 @@ class boss_thorim : public CreatureScript } }; +struct npc_thorim_trashAI : public ScriptedAI +{ + npc_thorim_trashAI(Creature* creature) : ScriptedAI(creature) + { + _instance = creature->GetInstanceScript(); + for (uint8 i = 0; i < ThorimTrashCount; ++i) + if (me->GetEntry() == StaticThorimTrashInfo[i].Entry) + _info = &StaticThorimTrashInfo[i]; + + ASSERT(_info); + } + + struct AIHelper + { + /// returns heal amount of the given spell including hots + static uint32 GetTotalHeal(SpellInfo const* spellInfo, Unit const* caster) + { + uint32 heal = 0; + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (spellInfo->Effects[i].IsEffect(SPELL_EFFECT_HEAL)) + heal += spellInfo->Effects[i].CalcValue(caster); + + if (spellInfo->Effects[i].IsEffect(SPELL_EFFECT_APPLY_AURA) && spellInfo->Effects[i].IsAura(SPELL_AURA_PERIODIC_HEAL)) + heal += spellInfo->GetMaxTicks() * spellInfo->Effects[i].CalcValue(caster); + } + return heal; + } + + /// returns remaining heal amount on given target + static uint32 GetRemainingHealOn(Unit* target) + { + uint32 heal = 0; + Unit::AuraEffectList const& auras = target->GetAuraEffectsByType(SPELL_AURA_PERIODIC_HEAL); + for (AuraEffect const* aurEff : auras) + heal += aurEff->GetAmount() * (aurEff->GetTotalTicks() - aurEff->GetTickNumber()); + + return heal; + } + + class MostHPMissingInRange + { + public: + MostHPMissingInRange(Unit const* referer, float range, uint32 hp, uint32 exclAura = 0, bool exclSelf = false) + : _referer(referer), _range(range), _hp(hp), _exclAura(exclAura), _exclSelf(exclSelf) { } + + bool operator()(Unit* u) + { + if (_exclSelf && u == _referer) + return false; + + if (_exclAura && u->HasAura(sSpellMgr->GetSpellIdForDifficulty(_exclAura, _referer))) + return false; + + if ((u->GetHealth() + GetRemainingHealOn(u) + _hp) > u->GetMaxHealth()) + return false; + + uint32 missingHP = u->GetMaxHealth() - u->GetHealth(); + if (u->IsAlive() && _referer->IsFriendlyTo(u) && _referer->IsWithinDistInMap(u, _range) && missingHP > _hp) + { + _hp = missingHP; + return true; + } + + return false; + } + + private: + Unit const* _referer; + float _range; + uint32 _hp; + uint32 _exclAura; + bool _exclSelf; + }; + + static Unit* GetUnitWithMostMissingHp(SpellInfo const* spellInfo, Unit* caster) + { + // use positive range, it's a healing spell + float const range = spellInfo->GetMaxRange(true); + uint32 const heal = GetTotalHeal(spellInfo, caster); + + Unit* target = nullptr; + MostHPMissingInRange checker(caster, range, heal); + Trinity::UnitLastSearcher searcher(caster, target, checker); + caster->VisitNearbyObject(range, searcher); + + return target; + } + + static Unit* GetHealTarget(SpellInfo const* spellInfo, Unit* caster) + { + Unit* healTarget = nullptr; + if (!spellInfo->HasAttribute(SPELL_ATTR1_CANT_TARGET_SELF) && !roll_chance_f(caster->GetHealthPct()) && ((caster->GetHealth() + GetRemainingHealOn(caster) + GetTotalHeal(spellInfo, caster)) <= caster->GetMaxHealth())) + healTarget = caster; + else + healTarget = GetUnitWithMostMissingHp(spellInfo, caster); + + return healTarget; + } + }; + + bool UseAbility(uint32 spellId) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); + if (!spellInfo) + return false; + + Unit* target = nullptr; + if (AIHelper::GetTotalHeal(spellInfo, me)) + target = AIHelper::GetHealTarget(spellInfo, me); + else + target = me->GetVictim(); + + if (!target) + return false; + + if (_info->Type == MERCENARY_SOLDIER) + { + bool allowMove = true; + if (me->IsInRange(target, spellInfo->GetMinRange(), spellInfo->GetMaxRange())) + allowMove = false; + + if (IsCombatMovementAllowed() != allowMove) + { + SetCombatMovement(allowMove); + + // need relaunch movement + ScriptedAI::AttackStart(target); + + // give some time to allow reposition, try again in a second + if (allowMove) + return false; + } + } + + DoCast(target, spellId); + return true; + } + + void UpdateAI(uint32 diff) final override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + ExecuteEvent(eventId); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + + if (_info->Type == DARK_RUNE_ACOLYTE) + DoSpellAttackIfReady(SPELL_HOLY_SMITE); + else + DoMeleeAttackIfReady(); + } + + virtual void ExecuteEvent(uint32 eventId) = 0; + +protected: + InstanceScript* _instance; + EventMap _events; + + ThorimTrashInfo const* _info = nullptr; +}; + +class npc_thorim_pre_phase : public CreatureScript +{ + public: + npc_thorim_pre_phase() : CreatureScript("npc_thorim_pre_phase") { } + + struct npc_thorim_pre_phaseAI : public npc_thorim_trashAI + { + npc_thorim_pre_phaseAI(Creature* creature) : npc_thorim_trashAI(creature) + { + me->setActive(true); // prevent grid unload + } + + void Reset() override + { + _events.Reset(); + if (_info->PrimaryAbility) + _events.ScheduleEvent(EVENT_PRIMARY_ABILITY, urand(3000, 6000)); + if (_info->SecondaryAbility) + _events.ScheduleEvent(EVENT_SECONDARY_ABILITY, _info->SecondaryAbility == SPELL_SHOOT ? 2000 : urand(12000, 15000)); + if (_info->ThirdAbility) + _events.ScheduleEvent(EVENT_THIRD_ABILITY, urand(6000, 8000)); + if (_info->Type == MERCENARY_SOLDIER) + SetCombatMovement(false); + } + + void JustDied(Unit* /*victim*/) override + { + if (Creature* thorim = _instance->GetCreature(BOSS_THORIM)) + thorim->AI()->DoAction(ACTION_INCREASE_PREADDS_COUNT); + } + + bool ShouldSparWith(Unit const* target) const override + { + return !target->GetAffectingPlayer(); + } + + void DamageTaken(Unit* attacker, uint32& damage) override + { + // nullify spell damage + if (!attacker->GetAffectingPlayer()) + damage = 0; + } + + void ExecuteEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_PRIMARY_ABILITY: + if (UseAbility(_info->PrimaryAbility)) + _events.ScheduleEvent(eventId, urand(15000, 20000)); + else + _events.ScheduleEvent(eventId, 1000); + break; + case EVENT_SECONDARY_ABILITY: + if (UseAbility(_info->SecondaryAbility)) + _events.ScheduleEvent(eventId, _info->SecondaryAbility == SPELL_SHOOT ? 2000 : urand(4000, 8000)); + else + _events.ScheduleEvent(eventId, 1000); + break; + case EVENT_THIRD_ABILITY: + if (UseAbility(_info->ThirdAbility)) + _events.ScheduleEvent(eventId, urand(6000, 8000)); + else + _events.ScheduleEvent(eventId, 1000); + break; + default: + break; + } + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_thorim_arena_phase : public CreatureScript +{ + public: + npc_thorim_arena_phase() : CreatureScript("npc_thorim_arena_phase") { } + + struct npc_thorim_arena_phaseAI : public npc_thorim_trashAI + { + npc_thorim_arena_phaseAI(Creature* creature) : npc_thorim_trashAI(creature) + { + switch (_info->Type) + { + case DARK_RUNE_CHAMPION: + case DARK_RUNE_WARBRINGER: + case DARK_RUNE_COMMONER: + case DARK_RUNE_EVOKER: + _isInArena = true; + break; + case DARK_RUNE_ACOLYTE: + { + _isInArena = (_info->Entry == NPC_DARK_RUNE_ACOLYTE_PRE); + SetBoundary(&ArenaBoundaries, !_isInArena); + break; + } + default: + _isInArena = false; + break; + } + } + + bool CanAIAttack(Unit const* who) const override + { + // don't try to attack players in balcony + if (_isInArena && HeightPositionCheck(true)(who)) + return false; + + return CheckBoundary(who); + } + + void Reset() override + { + _events.Reset(); + if (_info->PrimaryAbility) + _events.ScheduleEvent(EVENT_PRIMARY_ABILITY, urand(3000, 6000)); + if (_info->SecondaryAbility) + _events.ScheduleEvent(EVENT_SECONDARY_ABILITY, urand(7000, 9000)); + if (_info->ThirdAbility) + _events.ScheduleEvent(EVENT_THIRD_ABILITY, urand(6000, 8000)); + if (_info->Type == DARK_RUNE_CHAMPION) + _events.ScheduleEvent(EVENT_ABILITY_CHARGE, 8000); + } + + void EnterCombat(Unit* /*who*/) override + { + if (_info->Type == DARK_RUNE_WARBRINGER) + DoCast(me, SPELL_AURA_OF_CELERITY); + + if (!_isInArena) + if (Creature* colossus = _instance->GetCreature(DATA_RUNIC_COLOSSUS)) + colossus->AI()->DoAction(ACTION_ACTIVATE_RUNIC_SMASH); + } + + void EnterEvadeMode(EvadeReason why) override + { + if (why != EVADE_REASON_NO_HOSTILES && why != EVADE_REASON_BOUNDARY) + return; + + // this should only happen if theres no alive player in the arena -> summon orb + if (Creature* thorim = _instance->GetCreature(BOSS_THORIM)) + thorim->AI()->DoAction(ACTION_BERSERK); + ScriptedAI::EnterEvadeMode(why); + } + + void ExecuteEvent(uint32 eventId) override + { + switch (eventId) + { + case EVENT_PRIMARY_ABILITY: + if (UseAbility(_info->PrimaryAbility)) + _events.Repeat(3000, 6000); + else + _events.Repeat(1000); + break; + case EVENT_SECONDARY_ABILITY: + if (UseAbility(_info->SecondaryAbility)) + _events.Repeat(12000, 16000); + else + _events.Repeat(1000); + break; + case EVENT_THIRD_ABILITY: + if (UseAbility(_info->ThirdAbility)) + _events.Repeat(6000, 8000); + else + _events.Repeat(1000); + break; + case EVENT_ABILITY_CHARGE: + { + Unit* referer = me; + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 25.0f); })) + DoCast(target, SPELL_CHARGE); + _events.ScheduleEvent(eventId, 12000); + break; + } + default: + break; + } + } + + private: + bool _isInArena; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +struct npc_thorim_minibossAI : public ScriptedAI +{ + npc_thorim_minibossAI(Creature* creature) : ScriptedAI(creature), _summons(me) + { + _instance = creature->GetInstanceScript(); + + SetBoundary(&ArenaBoundaries, true); + } + + bool CanAIAttack(Unit const* who) const final override + { + return CheckBoundary(who); + } + + void JustSummoned(Creature* summon) final override + { + _summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature* summon) final override + { + _summons.Despawn(summon); + } + + void DoAction(int32 action) override + { + if (action == ACTION_ACTIVATE_ADDS) + { + for (ObjectGuid const& guid : _summons) + if (Creature* summon = ObjectAccessor::GetCreature(*me, guid)) + summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + } + } + +protected: + InstanceScript* _instance; + EventMap _events; + SummonList _summons; +}; + +class npc_runic_colossus : public CreatureScript +{ + public: + npc_runic_colossus() : CreatureScript("npc_runic_colossus") { } + + struct npc_runic_colossusAI : public npc_thorim_minibossAI + { + npc_runic_colossusAI(Creature* creature) : npc_thorim_minibossAI(creature) + { + Initialize(); + } + + void Initialize() + { + _runicActive = false; + } + + void Reset() override + { + Initialize(); + _events.Reset(); + + // close the Runic Door + _instance->HandleGameObject(_instance->GetGuidData(DATA_RUNIC_DOOR), false); + + // Spawn trashes + _summons.DespawnAll(); + for (SummonLocation const& s : ColossusAddLocations) + me->SummonCreature(s.entry, s.pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + } + + void MoveInLineOfSight(Unit* /*who*/) override + { + // don't enter combat + } + + void DoAction(int32 action) override + { + npc_thorim_minibossAI::DoAction(action); + + if (_runicActive) + return; + + if (action == ACTION_ACTIVATE_RUNIC_SMASH) + { + _runicActive = true; + _events.ScheduleEvent(EVENT_RUNIC_SMASH, 7000); + } + } + + void JustDied(Unit* /*victim*/) override + { + // open the Runic Door + _instance->HandleGameObject(_instance->GetGuidData(DATA_RUNIC_DOOR), true); + + if (Creature* thorim = _instance->GetCreature(BOSS_THORIM)) + thorim->AI()->Talk(SAY_SPECIAL); + + if (Creature* giant = _instance->GetCreature(DATA_RUNE_GIANT)) + { + giant->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); + giant->AI()->DoAction(ACTION_ACTIVATE_ADDS); + } + } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + _events.Reset(); + _events.ScheduleEvent(EVENT_RUNIC_BARRIER, urand(12000, 15000)); + _events.ScheduleEvent(EVENT_SMASH, urand(15000, 18000)); + _events.ScheduleEvent(EVENT_RUNIC_CHARGE, urand(20000, 24000)); + } + + void UpdateAI(uint32 diff) override + { + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_RUNIC_BARRIER: + Talk(EMOTE_RUNIC_BARRIER); + DoCastAOE(SPELL_RUNIC_BARRIER); + _events.Repeat(35000, 45000); + break; + case EVENT_SMASH: + DoCastAOE(SPELL_SMASH); + _events.Repeat(15000, 18000); + break; + case EVENT_RUNIC_CHARGE: + { + Unit* referer = me; + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, [referer](Unit* unit){ return unit->GetTypeId() == TYPEID_PLAYER && unit->IsInRange(referer, 8.0f, 40.0f); })) + DoCast(target, SPELL_RUNIC_CHARGE); + _events.Repeat(20000); + break; + } + case EVENT_RUNIC_SMASH: + DoCast(me, RAND(SPELL_RUNIC_SMASH_LEFT, SPELL_RUNIC_SMASH_RIGHT)); + _events.Repeat(6000); + break; + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + private: + bool _runicActive; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_ancient_rune_giant : public CreatureScript +{ + public: + npc_ancient_rune_giant() : CreatureScript("npc_ancient_rune_giant") { } + + struct npc_ancient_rune_giantAI : public npc_thorim_minibossAI + { + npc_ancient_rune_giantAI(Creature* creature) : npc_thorim_minibossAI(creature) { } + + void Reset() override + { + _events.Reset(); + + // close the Stone Door + _instance->HandleGameObject(_instance->GetGuidData(DATA_STONE_DOOR), false); + + // Spawn trashes + _summons.DespawnAll(); + for (SummonLocation const& s : GiantAddLocations) + me->SummonCreature(s.entry, s.pos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000); + } + + void EnterCombat(Unit* /*who*/) override + { + DoZoneInCombat(); + _events.Reset(); + _events.ScheduleEvent(EVENT_RUNIC_FORTIFICATION, 1); + _events.ScheduleEvent(EVENT_STOMP, urand(10000, 12000)); + _events.ScheduleEvent(EVENT_RUNE_DETONATION, 25000); + } + + void JustDied(Unit* /*victim*/) override + { + // opem the Stone Door + _instance->HandleGameObject(_instance->GetGuidData(DATA_STONE_DOOR), true); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_RUNIC_FORTIFICATION: + Talk(EMOTE_RUNIC_MIGHT); + DoCastAOE(SPELL_RUNIC_FORTIFICATION); + break; + case EVENT_STOMP: + DoCastAOE(SPELL_STOMP); + _events.Repeat(10000, 12000); + break; + case EVENT_RUNE_DETONATION: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, true)) + DoCast(target, SPELL_RUNE_DETONATION); + _events.Repeat(10000, 12000); + break; + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + + DoMeleeAttackIfReady(); + } + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +class npc_sif : public CreatureScript +{ + public: + npc_sif() : CreatureScript("npc_sif") { } + + struct npc_sifAI : public ScriptedAI + { + npc_sifAI(Creature* creature) : ScriptedAI(creature) + { + SetCombatMovement(false); + _instance = creature->GetInstanceScript(); + } + + void Reset() override + { + _events.Reset(); + } + + void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override + { + if (spellInfo->Id == SPELL_STORMHAMMER_SIF) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->SetReactState(REACT_PASSIVE); + me->AttackStop(); + } + } + + void DoAction(int32 action) override + { + if (action == ACTION_START_HARD_MODE) + { + me->SetReactState(REACT_AGGRESSIVE); + DoZoneInCombat(me, 250.0f); + Talk(SAY_SIF_EVENT); + _events.Reset(); + _events.ScheduleEvent(EVENT_FROSTBOLT, 2000); + _events.ScheduleEvent(EVENT_FROSTBOLT_VOLLEY, 15000); + _events.ScheduleEvent(EVENT_BLINK, urand(20000, 25000)); + _events.ScheduleEvent(EVENT_BLIZZARD, 30000); + } + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + return; + + _events.Update(diff); + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + + while (uint32 eventId = _events.ExecuteEvent()) + { + switch (eventId) + { + case EVENT_BLINK: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_BLINK); + _events.ScheduleEvent(EVENT_FROST_NOVA, 0); + _events.Repeat(20000, 25000); + return; + case EVENT_FROST_NOVA: + DoCastAOE(SPELL_FROSTNOVA); + return; + case EVENT_FROSTBOLT: + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) + DoCast(target, SPELL_FROSTBOLT); + _events.Repeat(2000); + return; + case EVENT_FROSTBOLT_VOLLEY: + DoCastAOE(SPELL_FROSTBOLT_VOLLEY); + _events.Repeat(15000, 20000); + return; + case EVENT_BLIZZARD: + DoCastAOE(SPELL_BLIZZARD); + _events.Repeat(35000, 45000); + return; + default: + break; + } + + if (me->HasUnitState(UNIT_STATE_CASTING)) + return; + } + + // no melee attack + } + + private: + EventMap _events; + InstanceScript* _instance; + }; + + CreatureAI* GetAI(Creature* creature) const override + { + return GetUlduarAI(creature); + } +}; + +// 62576 - Blizzard +// 62602 - Blizzard +class spell_thorim_blizzard_effect : public SpellScriptLoader +{ + public: + spell_thorim_blizzard_effect() : SpellScriptLoader("spell_thorim_blizzard_effect") { } + + class spell_thorim_blizzard_effect_AuraScript : public AuraScript + { + PrepareAuraScript(spell_thorim_blizzard_effect_AuraScript); + + bool CheckAreaTarget(Unit* target) + { + /// @todo: fix this for all dynobj auras + if (target != GetOwner()) + { + // check if not stacking aura already on target + // this one prevents overriding auras periodically by 2 near area aura owners + Unit::AuraApplicationMap const& auraMap = target->GetAppliedAuras(); + for (Unit::AuraApplicationMap::const_iterator iter = auraMap.begin(); iter != auraMap.end(); ++iter) + { + Aura const* aura = iter->second->GetBase(); + if (GetId() == aura->GetId() && GetOwner() != aura->GetOwner() /*!GetAura()->CanStackWith(aura)*/) + return false; + } + } + + return true; + } + + void Register() override + { + DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_thorim_blizzard_effect_AuraScript::CheckAreaTarget); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_thorim_blizzard_effect_AuraScript(); + } +}; + +// 62580, 62604 - Frostbolt Volley +class spell_thorim_frostbolt_volley : public SpellScriptLoader +{ + public: + spell_thorim_frostbolt_volley() : SpellScriptLoader("spell_thorim_frostbolt_volley") { } + + class spell_thorim_frostbolt_volley_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_frostbolt_volley_SpellScript); + + void FilterTargets(std::list& unitList) + { + unitList.remove_if(PlayerOrPetCheck()); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thorim_frostbolt_volley_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_frostbolt_volley_SpellScript(); + } +}; + +// 62016 - Charge Orb +class spell_thorim_charge_orb : public SpellScriptLoader +{ + public: + spell_thorim_charge_orb() : SpellScriptLoader("spell_thorim_charge_orb") { } + + class spell_thorim_charge_orb_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_charge_orb_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_LIGHTNING_PILLAR_1)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + targets.remove_if(HeightPositionCheck(false)); + + if (targets.empty()) + return; + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + + void HandleScript() + { + if (Unit* target = GetHitUnit()) + target->CastSpell((Unit*)nullptr, SPELL_LIGHTNING_PILLAR_1, true); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thorim_charge_orb_SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_SRC_AREA_ENTRY); + AfterHit += SpellHitFn(spell_thorim_charge_orb_SpellScript::HandleScript); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_charge_orb_SpellScript(); + } +}; + +// 62466 - Lightning Charge +class spell_thorim_lightning_charge : public SpellScriptLoader +{ + public: + spell_thorim_lightning_charge() : SpellScriptLoader("spell_thorim_lightning_charge") { } + + class spell_thorim_lightning_charge_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_lightning_charge_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_LIGHTNING_CHARGE)) + return false; + return true; + } + + void HandleFocus() + { + /// @workaround: focus target is not working because spell is triggered and instant + if (Creature* creature = GetCaster()->ToCreature()) + creature->FocusTarget(GetSpell(), GetExplTargetWorldObject()); + } + + void HandleCharge() + { + GetCaster()->CastSpell(GetCaster(), SPELL_LIGHTNING_CHARGE); + } + + void Register() override + { + BeforeCast += SpellCastFn(spell_thorim_lightning_charge_SpellScript::HandleFocus); + AfterCast += SpellCastFn(spell_thorim_lightning_charge_SpellScript::HandleCharge); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_lightning_charge_SpellScript(); + } +}; + +// 61934 - Leap +class spell_thorim_arena_leap : public SpellScriptLoader +{ + public: + spell_thorim_arena_leap() : SpellScriptLoader("spell_thorim_arena_leap") { } + + class spell_thorim_arena_leap_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_arena_leap_SpellScript); + + bool Load() override + { + return GetCaster()->GetTypeId() == TYPEID_UNIT; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Position const* pos = GetHitDest()) + GetCaster()->ToCreature()->SetHomePosition(*pos); + } + + void Register() override + { + OnEffectLaunch += SpellEffectFn(spell_thorim_arena_leap_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_JUMP_DEST); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_arena_leap_SpellScript(); + } +}; + +struct OutOfArenaCheck +{ + bool operator()(Position const* who) const + { + return !CreatureAI::IsInBounds(ArenaBoundaries, who); + } +}; + +// 62042 - Stormhammer +class spell_thorim_stormhammer : public SpellScriptLoader +{ + public: + spell_thorim_stormhammer() : SpellScriptLoader("spell_thorim_stormhammer") { } + + class spell_thorim_stormhammer_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_stormhammer_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_STORMHAMMER_BOOMERANG) + || !sSpellMgr->GetSpellInfo(SPELL_DEAFENING_THUNDER)) + return false; + return true; + } + + void FilterTargets(std::list& targets) + { + targets.remove_if([](WorldObject* target) -> bool { return HeightPositionCheck(true)(target) || OutOfArenaCheck()(target); }); + + if (targets.empty()) + { + FinishCast(SPELL_FAILED_NO_VALID_TARGETS); + return; + } + + WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets); + targets.clear(); + targets.push_back(target); + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->CastSpell(target, SPELL_DEAFENING_THUNDER, true); + target->CastSpell(GetCaster(), SPELL_STORMHAMMER_BOOMERANG, true); + } + } + + void LoseHammer() + { + GetCaster()->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + } + + void Register() override + { + OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_thorim_stormhammer_SpellScript::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ENEMY); + AfterCast += SpellCastFn(spell_thorim_stormhammer_SpellScript::LoseHammer); + OnEffectHitTarget += SpellEffectFn(spell_thorim_stormhammer_SpellScript::HandleScript, EFFECT_2, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_stormhammer_SpellScript(); + } +}; + +// 64767 - Stormhammer +class spell_thorim_stormhammer_sif : public SpellScriptLoader +{ + public: + spell_thorim_stormhammer_sif() : SpellScriptLoader("spell_thorim_stormhammer_sif") { } + + class spell_thorim_stormhammer_sif_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_stormhammer_sif_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_STORMHAMMER_BOOMERANG) + || !sSpellMgr->GetSpellInfo(SPELL_SIF_TRANSFORM)) + return false; + return true; + } + + void HandleScript(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + { + target->CastSpell(GetCaster(), SPELL_STORMHAMMER_BOOMERANG, true); + target->CastSpell(target, SPELL_SIF_TRANSFORM, true); + } + } + + void LoseHammer() + { + GetCaster()->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + } + + void Register() override + { + AfterCast += SpellCastFn(spell_thorim_stormhammer_sif_SpellScript::LoseHammer); + OnEffectHitTarget += SpellEffectFn(spell_thorim_stormhammer_sif_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_stormhammer_sif_SpellScript(); + } +}; + +// 64909 - Stormhammer +class spell_thorim_stormhammer_boomerang : public SpellScriptLoader +{ + public: + spell_thorim_stormhammer_boomerang() : SpellScriptLoader("spell_thorim_stormhammer_boomerang") { } + + class spell_thorim_stormhammer_boomerang_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_stormhammer_boomerang_SpellScript); + + void RecoverHammer(SpellEffIndex /*effIndex*/) + { + if (Unit* target = GetHitUnit()) + target->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THORIM_WEAPON_DISPLAY_ID); + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_thorim_stormhammer_boomerang_SpellScript::RecoverHammer, EFFECT_0, SPELL_EFFECT_DUMMY); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_stormhammer_boomerang_SpellScript(); + } +}; + +// 62057, 62058 - Runic Smash +class spell_thorim_runic_smash : public SpellScriptLoader +{ + public: + spell_thorim_runic_smash() : SpellScriptLoader("spell_thorim_runic_smash") { } + + class spell_thorim_runic_smash_SpellScript : public SpellScript + { + PrepareSpellScript(spell_thorim_runic_smash_SpellScript); + + bool Validate(SpellInfo const* /*spellInfo*/) override + { + if (!sSpellMgr->GetSpellInfo(SPELL_RUNIC_SMASH)) + return false; + return true; + } + + void HandleScript(SpellEffIndex effIndex) + { + PreventHitDefaultEffect(effIndex); + + std::vector triggers; + GetCaster()->GetCreatureListWithEntryInGrid(triggers, GetSpellInfo()->Id == SPELL_RUNIC_SMASH_LEFT ? NPC_GOLEM_LEFT_HAND_BUNNY : NPC_GOLEM_RIGHT_HAND_BUNNY, 150.0f); + for (Creature* trigger : triggers) + { + float dist = GetCaster()->GetExactDist(trigger); + trigger->m_Events.AddEvent(new RunicSmashExplosionEvent(trigger), trigger->m_Events.CalculateTime(uint64(dist * 30.f))); + }; + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_thorim_runic_smash_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_TRIGGER_SPELL); + } + }; + + SpellScript* GetSpellScript() const override + { + return new spell_thorim_runic_smash_SpellScript(); + } +}; + +class UpperOrbCheck +{ + public: + UpperOrbCheck() : _check(true) { } + + bool operator() (Creature* target) const + { + return target->GetEntry() == NPC_THUNDER_ORB && _check(target); + } + + private: + HeightPositionCheck const _check; +}; + +// 62184 - Activate Lightning Orb Periodic +class spell_thorim_activate_lightning_orb_periodic : public SpellScriptLoader +{ + public: + spell_thorim_activate_lightning_orb_periodic() : SpellScriptLoader("spell_thorim_activate_lightning_orb_periodic") { } + + class spell_thorim_activate_lightning_orb_periodic_AuraScript : public AuraScript + { + PrepareAuraScript(spell_thorim_activate_lightning_orb_periodic_AuraScript); + + InstanceScript* instance = nullptr; + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + PreventDefaultAction(); + + Unit* caster = GetCaster(); + std::vector triggers; + + UpperOrbCheck check; + Trinity::CreatureListSearcher searcher(caster, triggers, check); + caster->VisitNearbyGridObject(100.f, searcher); + + if (!triggers.empty()) + { + Creature* target = Trinity::Containers::SelectRandomContainerElement(triggers); + if (Creature* thorim = instance->GetCreature(BOSS_THORIM)) + thorim->AI()->SetGUID(target->GetGUID(), DATA_CHARGED_PILLAR); + } + } + + bool Load() override + { + if (Unit* caster = GetCaster()) + instance = caster->GetInstanceScript(); + + return instance != nullptr; + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_thorim_activate_lightning_orb_periodic_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_thorim_activate_lightning_orb_periodic_AuraScript(); + } +}; + +// 62331, 62418 - Impale +class spell_iron_ring_guard_impale : public SpellScriptLoader +{ + public: + spell_iron_ring_guard_impale() : SpellScriptLoader("spell_iron_ring_guard_impale") { } + + class spell_iron_ring_guard_impale_AuraScript : public AuraScript + { + PrepareAuraScript(spell_iron_ring_guard_impale_AuraScript); + + void PeriodicTick(AuraEffect const* /*aurEff*/) + { + if (GetTarget()->HealthAbovePct(GetSpellInfo()->Effects[EFFECT_1].CalcValue())) + { + Remove(AURA_REMOVE_BY_ENEMY_SPELL); + PreventDefaultAction(); + } + } + + void Register() override + { + OnEffectPeriodic += AuraEffectPeriodicFn(spell_iron_ring_guard_impale_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE); + } + }; + + AuraScript* GetAuraScript() const override + { + return new spell_iron_ring_guard_impale_AuraScript(); + } +}; + +class achievement_dont_stand_in_the_lightning : public AchievementCriteriaScript +{ + public: + achievement_dont_stand_in_the_lightning() : AchievementCriteriaScript("achievement_dont_stand_in_the_lightning") { } + + bool OnCheck(Player* /*source*/, Unit* target) override + { + return target && target->GetAI()->GetData(ACHIEVEMENT_DONT_STAND_IN_THE_LIGHTNING); + } +}; + +class achievement_lose_your_illusion : public AchievementCriteriaScript +{ + public: + achievement_lose_your_illusion() : AchievementCriteriaScript("achievement_lose_your_illusion") { } + + bool OnCheck(Player* /*source*/, Unit* target) override + { + return target && target->GetAI()->GetData(ACHIEVEMENT_LOSE_YOUR_ILLUSION); + } +}; + +class achievement_i_ll_take_you_all_on : public AchievementCriteriaScript +{ + public: + achievement_i_ll_take_you_all_on() : AchievementCriteriaScript("achievement_i_ll_take_you_all_on"), _check() { } + + bool OnCheck(Player* source, Unit* /*target*/) override + { + return _check(source); + } + + private: + OutOfArenaCheck _check; +}; + +class condition_thorim_arena_leap : public ConditionScript +{ + public: + condition_thorim_arena_leap() : ConditionScript("condition_thorim_arena_leap"), _check(false) { } + + bool OnConditionCheck(Condition const* condition, ConditionSourceInfo& sourceInfo) override + { + WorldObject* target = sourceInfo.mConditionTargets[condition->ConditionTarget]; + InstanceScript* instance = target->GetInstanceScript(); + + if (!instance) + return false; + + return _check(target); + } + + private: + HeightPositionCheck _check; +}; + void AddSC_boss_thorim() { new boss_thorim(); + new npc_thorim_pre_phase(); + new npc_thorim_arena_phase(); + new npc_runic_colossus(); + new npc_ancient_rune_giant(); + new npc_sif(); + new spell_thorim_blizzard_effect(); + new spell_thorim_frostbolt_volley(); + new spell_thorim_charge_orb(); + new spell_thorim_lightning_charge(); + new spell_thorim_stormhammer(); + new spell_thorim_stormhammer_sif(); + new spell_thorim_stormhammer_boomerang(); + new spell_thorim_arena_leap(); + new spell_thorim_runic_smash(); + new spell_thorim_activate_lightning_orb_periodic(); + new spell_iron_ring_guard_impale(); + new achievement_dont_stand_in_the_lightning(); + new achievement_lose_your_illusion(); + new achievement_i_ll_take_you_all_on(); + new condition_thorim_arena_leap(); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index 11036bcbb0..7fbb84e35b 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -765,7 +765,7 @@ class boss_sara : public CreatureScript { me->RemoveAllAuras(); me->SetReactState(REACT_PASSIVE); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); _events.Reset(); _events.SetPhase(PHASE_ONE); } @@ -808,7 +808,7 @@ class boss_sara : public CreatureScript case EVENT_TRANSFORM_3: Talk(SAY_SARA_TRANSFORM_4); DoCast(me, SPELL_FULL_HEAL); - me->SetFaction(16); + me->SetFaction(FACTION_MONSTER_2); if (Creature* voice = _instance->GetCreature(DATA_VOICE_OF_YOGG_SARON)) voice->AI()->DoAction(ACTION_PHASE_TWO); if (Creature* mimiron = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_MIMIRON_YS))) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp index 61275ff3e6..d662578b9d 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/instance_ulduar.cpp @@ -32,9 +32,9 @@ static BossBoundaryData const boundaries = { BOSS_XT002, new RectangleBoundary(755.0f, 940.0f, -125.0f, 95.0f) }, { BOSS_ASSEMBLY_OF_IRON, new CircleBoundary(Position(1587.2f, 121.0f), 90.0) }, { BOSS_ALGALON, new CircleBoundary(Position(1632.668f, -307.7656f), 45.0) }, - { BOSS_ALGALON, new ZRangeBoundary(410.0f, 440.0f) }, + { BOSS_ALGALON, new ZRangeBoundary(410.0f, 470.0f) }, { BOSS_HODIR, new EllipseBoundary(Position(2001.5f, -240.0f), 50.0, 75.0) }, - { BOSS_THORIM, new CircleBoundary(Position(2134.73f, -263.2f), 50.0) }, + // Thorim sets boundaries dynamically { BOSS_FREYA, new RectangleBoundary(2094.6f, 2520.0f, -250.0f, 200.0f) }, { BOSS_MIMIRON, new CircleBoundary(Position(2744.0f, 2569.0f), 70.0) }, { BOSS_VEZAX, new RectangleBoundary(1740.0f, 1930.0f, 31.0f, 228.0f) }, @@ -53,6 +53,11 @@ static DoorData const doorData[] = { GO_MIMIRON_DOOR_1, BOSS_MIMIRON, DOOR_TYPE_ROOM }, { GO_MIMIRON_DOOR_2, BOSS_MIMIRON, DOOR_TYPE_ROOM }, { GO_MIMIRON_DOOR_3, BOSS_MIMIRON, DOOR_TYPE_ROOM }, + { GO_THORIM_ENCOUNTER_DOOR, BOSS_THORIM, DOOR_TYPE_ROOM }, + { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_HODIR, DOOR_TYPE_PASSAGE }, + { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_MIMIRON, DOOR_TYPE_PASSAGE }, + { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_THORIM, DOOR_TYPE_PASSAGE }, + { GO_ANCIENT_GATE_OF_THE_KEEPERS, BOSS_FREYA, DOOR_TYPE_PASSAGE }, { GO_VEZAX_DOOR, BOSS_VEZAX, DOOR_TYPE_PASSAGE }, { GO_YOGG_SARON_DOOR, BOSS_YOGG_SARON, DOOR_TYPE_ROOM }, { GO_DOODAD_UL_SIGILDOOR_03, BOSS_ALGALON, DOOR_TYPE_ROOM }, @@ -89,6 +94,10 @@ ObjectData const creatureData[] = { NPC_EXPEDITION_COMMANDER, DATA_EXPEDITION_COMMANDER }, { NPC_RAZORSCALE_CONTROLLER, DATA_RAZORSCALE_CONTROL }, + { NPC_SIF, DATA_SIF }, + { NPC_RUNIC_COLOSSUS, DATA_RUNIC_COLOSSUS }, + { NPC_RUNE_GIANT, DATA_RUNE_GIANT }, + { NPC_THORIM_CONTROLLER, DATA_THORIM_CONTROLLER }, { NPC_COMPUTER, DATA_COMPUTER }, { NPC_WORLD_TRIGGER_MIMIRON, DATA_MIMIRON_WORLD_TRIGGER }, { NPC_VOICE_OF_YOGG_SARON, DATA_VOICE_OF_YOGG_SARON }, @@ -112,6 +121,9 @@ ObjectData const objectData[] = { GO_RAZOR_HARPOON_2, GO_RAZOR_HARPOON_2 }, { GO_RAZOR_HARPOON_3, GO_RAZOR_HARPOON_3 }, { GO_RAZOR_HARPOON_4, GO_RAZOR_HARPOON_4 }, + { GO_THORIM_LEVER, DATA_THORIM_LEVER }, + { GO_THORIM_STONE_DOOR, DATA_STONE_DOOR }, + { GO_THORIM_RUNIC_DOOR, DATA_RUNIC_DOOR }, { 0, 0 } }; @@ -167,7 +179,9 @@ class instance_ulduar : public InstanceMapScript ObjectGuid LeviathanGateGUID; ObjectGuid KologarnChestGUID; ObjectGuid KologarnBridgeGUID; - ObjectGuid ThorimChestGUID; + ObjectGuid ThorimDarkIronPortcullisGUID; + ObjectGuid CacheOfStormsGUID; + ObjectGuid CacheOfStormsHardmodeGUID; ObjectGuid HodirRareCacheGUID; ObjectGuid HodirChestGUID; ObjectGuid MimironTramGUID; @@ -324,6 +338,16 @@ class instance_ulduar : public InstanceMapScript creature->UpdateEntry(NPC_BATTLE_PRIEST_GINA); break; + // Thorim + case NPC_MERCENARY_CAPTAIN_H: + if (TeamInInstance == HORDE) + creature->UpdateEntry(NPC_MERCENARY_CAPTAIN_A); + break; + case NPC_MERCENARY_SOLDIER_H: + if (TeamInInstance == HORDE) + creature->UpdateEntry(NPC_MERCENARY_SOLDIER_A); + break; + // Freya case NPC_IRONBRANCH: ElderGUIDs[0] = creature->GetGUID(); @@ -439,9 +463,16 @@ class instance_ulduar : public InstanceMapScript if (GetBossState(BOSS_KOLOGARN) == DONE) HandleGameObject(ObjectGuid::Empty, false, gameObject); break; - case GO_THORIM_CHEST_HERO: - case GO_THORIM_CHEST: - ThorimChestGUID = gameObject->GetGUID(); + case GO_THORIM_DARK_IRON_PORTCULLIS: + ThorimDarkIronPortcullisGUID = gameObject->GetGUID(); + break; + case GO_CACHE_OF_STORMS_10: + case GO_CACHE_OF_STORMS_25: + CacheOfStormsGUID = gameObject->GetGUID(); + break; + case GO_CACHE_OF_STORMS_HARDMODE_10: + case GO_CACHE_OF_STORMS_HARDMODE_25: + CacheOfStormsHardmodeGUID = gameObject->GetGUID(); break; case GO_HODIR_RARE_CACHE_OF_WINTER_HERO: case GO_HODIR_RARE_CACHE_OF_WINTER: @@ -648,11 +679,23 @@ class instance_ulduar : public InstanceMapScript case BOSS_THORIM: if (state == DONE) { - if (GameObject* gameObject = instance->GetGameObject(ThorimChestGUID)) - gameObject->SetRespawnTime(gameObject->GetRespawnDelay()); + if (Creature* thorim = GetCreature(BOSS_THORIM)) + { + if (GameObject* cache = instance->GetGameObject(thorim->AI()->GetData(DATA_THORIM_HARDMODE) ? CacheOfStormsHardmodeGUID : CacheOfStormsGUID)) + { + cache->SetLootRecipient(thorim->GetLootRecipient()); + cache->SetRespawnTime(cache->GetRespawnDelay()); + cache->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE | GO_FLAG_NODESPAWN); + } + } instance->SummonCreature(NPC_THORIM_OBSERVATION_RING, ObservationRingKeepersPos[2]); } + else + { + DoCloseDoorOrButton(GetGuidData(DATA_THORIM_LEVER)); + DoCloseDoorOrButton(ThorimDarkIronPortcullisGUID); + } break; case BOSS_ALGALON: if (state == DONE) @@ -871,7 +914,6 @@ class instance_ulduar : public InstanceMapScript return keepersCount <= 1; case CRITERIA_ALONE_IN_THE_DARKNESS_10: case CRITERIA_ALONE_IN_THE_DARKNESS_25: - case CRITERIA_DEATHS_DEMISE: return keepersCount == 0; case CRITERIA_C_O_U_LEVIATHAN_10: case CRITERIA_C_O_U_LEVIATHAN_25: diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h index 928a3eebf8..1596453464 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/ulduar.h @@ -153,6 +153,31 @@ enum UlduarNPCs // Freya Achievement Trigger NPC_FREYA_ACHIEVE_TRIGGER = 33406, + // Thorim + NPC_THORIM_INVISIBLE_STALKER = 32780, + NPC_JORMUNGAR_BEHEMOTH = 32882, + NPC_MERCENARY_CAPTAIN_A = 32908, + NPC_MERCENARY_CAPTAIN_H = 32907, + NPC_MERCENARY_SOLDIER_A = 32885, + NPC_MERCENARY_SOLDIER_H = 32883, + NPC_DARK_RUNE_ACOLYTE_PRE = 32886, + NPC_RUNIC_COLOSSUS = 32872, + NPC_RUNE_GIANT = 32873, + NPC_IRON_RING_GUARD = 32874, + NPC_IRON_HONOR_GUARD = 32875, + NPC_DARK_RUNE_CHAMPION = 32876, + NPC_DARK_RUNE_WARBRINGER = 32877, + NPC_DARK_RUNE_EVOKER = 32878, + NPC_DARK_RUNE_COMMONER = 32904, + NPC_DARK_RUNE_ACOLYTE = 33110, + NPC_THORIM_EVENT_BUNNY = 32892, + NPC_LIGHTNING_ORB = 33138, + NPC_GOLEM_RIGHT_HAND_BUNNY = 33140, + NPC_GOLEM_LEFT_HAND_BUNNY = 33141, + NPC_SIF = 33196, + NPC_THUNDER_ORB = 33378, + NPC_THORIM_CONTROLLER = 32879, + // Yogg-Saron NPC_SARA = 33134, NPC_GUARDIAN_OF_YOGG_SARON = 33136, @@ -227,6 +252,8 @@ enum UlduarGameObjects GO_KOLOGARN_BRIDGE = 194232, GO_KOLOGARN_DOOR = 194553, + GO_ANCIENT_GATE_OF_THE_KEEPERS = 194255, + // Hodir GO_HODIR_ENTRANCE = 194442, GO_HODIR_DOOR = 194634, @@ -237,8 +264,15 @@ enum UlduarGameObjects GO_HODIR_CHEST = 194307, // Thorim - GO_THORIM_CHEST_HERO = 194315, - GO_THORIM_CHEST = 194314, + GO_CACHE_OF_STORMS_10 = 194312, + GO_CACHE_OF_STORMS_HARDMODE_10 = 194313, + GO_CACHE_OF_STORMS_25 = 194315, + GO_CACHE_OF_STORMS_HARDMODE_25 = 194314, + GO_THORIM_RUNIC_DOOR = 194557, + GO_THORIM_STONE_DOOR = 194558, + GO_THORIM_ENCOUNTER_DOOR = 194559, + GO_THORIM_LEVER = 194264, + GO_THORIM_DARK_IRON_PORTCULLIS = 194560, // Mimiron GO_MIMIRON_TRAM = 194675, @@ -275,7 +309,7 @@ enum UlduarGameObjects GO_GIFT_OF_THE_OBSERVER_25 = 194822, }; -enum EventIds +enum UUEventIds { EVENT_TOWER_OF_STORM_DESTROYED = 21031, EVENT_TOWER_OF_FROST_DESTROYED = 21032, @@ -315,7 +349,6 @@ enum UlduarAchievementCriteriaIds CRITERIA_ONE_LIGHT_IN_THE_DARKNESS_25 = 10416, CRITERIA_ALONE_IN_THE_DARKNESS_10 = 10412, CRITERIA_ALONE_IN_THE_DARKNESS_25 = 10417, - CRITERIA_DEATHS_DEMISE = 10279, CRITERIA_HERALD_OF_TITANS = 10678, // Champion of Ulduar @@ -404,6 +437,16 @@ enum UlduarData DATA_ALGALON_TRAPDOOR, DATA_BRANN_BRONZEBEARD_ALG, + // Thorim + DATA_SIF, + DATA_THORIM_LEVER, + DATA_RUNIC_COLOSSUS, + DATA_RUNE_GIANT, + DATA_RUNIC_DOOR, + DATA_STONE_DOOR, + DATA_THORIM_HARDMODE, + DATA_THORIM_CONTROLLER, + // Misc DATA_BRANN_BRONZEBEARD_INTRO, DATA_LORE_KEEPER_OF_NORGANNON, @@ -420,10 +463,15 @@ enum UlduarWorldStates enum UlduarAchievementData { // FL Achievement boolean - DATA_UNBROKEN = 29052906, // 2905, 2906 are achievement IDs, + DATA_UNBROKEN = 29052906, // 2905, 2906 are achievement IDs, MAX_HERALD_ARMOR_ITEMLEVEL = 226, - MAX_HERALD_WEAPON_ITEMLEVEL = 232, - SPELL_LUMBERJACKED_CREDIT = 65296 + MAX_HERALD_WEAPON_ITEMLEVEL = 232 +}; + +enum UlduarSharedSpells +{ + SPELL_LUMBERJACKED_CREDIT = 65296, + SPELL_TELEPORT_KEEPER_VISUAL = 62940 // used by keepers }; enum UlduarEvents @@ -448,6 +496,23 @@ AI* GetUlduarAI(T* obj) return GetInstanceAI(obj, UlduarScriptName); } +class KeeperDespawnEvent : public BasicEvent +{ + public: + KeeperDespawnEvent(Creature* owner, uint32 despawnTimerOffset = 500) : _owner(owner), _despawnTimer(despawnTimerOffset) { } + + bool Execute(uint64 /*eventTime*/, uint32 /*updateTime*/) override + { + _owner->CastSpell(_owner, SPELL_TELEPORT_KEEPER_VISUAL); + _owner->DespawnOrUnsummon(1000 + _despawnTimer); + return true; + } + + private: + Creature* _owner; + uint32 _despawnTimer; +}; + class PlayerOrPetCheck { public: diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp index 6054b5d457..3ce72ebd74 100644 --- a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp +++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp @@ -240,7 +240,7 @@ class npc_ichor_globule : public CreatureScript struct npc_ichor_globuleAI : public ScriptedAI { - npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature) + npc_ichor_globuleAI(Creature* creature) : ScriptedAI(creature), _splashTriggered(false) { _instance = creature->GetInstanceScript(); creature->SetReactState(REACT_PASSIVE); @@ -272,14 +272,21 @@ class npc_ichor_globule : public CreatureScript // this feature should be still implemented void DamageTaken(Unit* /*attacker*/, uint32& damage) override { + if (_splashTriggered) + return; + if (damage >= me->GetHealth()) + { + _splashTriggered = true; DoCastAOE(SPELL_SPLASH); + } } void UpdateAI(uint32 /*diff*/) override { } private: InstanceScript* _instance; + bool _splashTriggered; }; CreatureAI* GetAI(Creature* creature) const override diff --git a/src/server/scripts/Northrend/northrend_script_loader.cpp b/src/server/scripts/Northrend/northrend_script_loader.cpp index 4678eb7843..e3c5fb720a 100644 --- a/src/server/scripts/Northrend/northrend_script_loader.cpp +++ b/src/server/scripts/Northrend/northrend_script_loader.cpp @@ -110,6 +110,7 @@ void AddSC_boss_general_vezax(); void AddSC_boss_mimiron(); void AddSC_boss_hodir(); void AddSC_boss_freya(); +void AddSC_boss_thorim(); void AddSC_boss_yogg_saron(); void AddSC_boss_algalon_the_observer(); void AddSC_instance_ulduar(); @@ -291,6 +292,7 @@ void AddNorthrendScripts() AddSC_boss_mimiron(); AddSC_boss_hodir(); AddSC_boss_freya(); + AddSC_boss_thorim(); AddSC_boss_yogg_saron(); AddSC_boss_algalon_the_observer(); AddSC_instance_ulduar(); diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index f81c06b5a3..3eaf0cc4ac 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -115,7 +115,7 @@ public: DoCast(me, SPELL_EXPLODE_CART, true); DoCast(me, SPELL_SUMMON_CART, true); if (GameObject* cart = me->FindNearestGameObject(GO_EXPLOSIVES_CART, 3.0f)) - cart->SetFaction(14); + cart->SetFaction(FACTION_MONSTER); phaseTimer = 3000; phase = 2; break; @@ -536,9 +536,6 @@ enum Lurgglbr GO_CAGE = 187369, - FACTION_ESCORTEE_A = 774, - FACTION_ESCORTEE_H = 775, - SAY_START_1 = 0, SAY_START_2 = 1, SAY_END_1 = 2, @@ -667,11 +664,11 @@ public: switch (player->GetTeam()) { case ALLIANCE: - creature->SetFaction(FACTION_ESCORTEE_A); + creature->SetFaction(FACTION_ESCORTEE_A_PASSIVE); break; default: case HORDE: - creature->SetFaction(FACTION_ESCORTEE_H); + creature->SetFaction(FACTION_ESCORTEE_H_PASSIVE); break; } @@ -1628,10 +1625,10 @@ public: switch (player->GetTeam()) { case ALLIANCE: - creature->SetFaction(FACTION_ESCORTEE_A); + creature->SetFaction(FACTION_ESCORTEE_A_PASSIVE); break; case HORDE: - creature->SetFaction(FACTION_ESCORTEE_H); + creature->SetFaction(FACTION_ESCORTEE_H_PASSIVE); break; } creature->SetStandState(UNIT_STAND_STATE_STAND); diff --git a/src/server/scripts/Northrend/zone_dragonblight.cpp b/src/server/scripts/Northrend/zone_dragonblight.cpp index b1b838eec1..6a8bbf25de 100644 --- a/src/server/scripts/Northrend/zone_dragonblight.cpp +++ b/src/server/scripts/Northrend/zone_dragonblight.cpp @@ -379,9 +379,7 @@ enum StrengthenAncientsMisc SPELL_CREATE_ITEM_BARK = 47550, SPELL_CONFUSED = 47044, - NPC_LOTHALOR = 26321, - - FACTION_WALKER_ENEMY = 14, + NPC_LOTHALOR = 26321 }; class spell_q12096_q12092_dummy : public SpellScriptLoader // Strengthen the Ancients: On Interact Dummy to Woodlands Walker @@ -414,7 +412,7 @@ public: else if (roll == 0) // enemy version { tree->AI()->Talk(SAY_WALKER_ENEMY, player); - tree->SetFaction(FACTION_WALKER_ENEMY); + tree->SetFaction(FACTION_MONSTER); tree->Attack(player, true); } } diff --git a/src/server/scripts/Northrend/zone_grizzly_hills.cpp b/src/server/scripts/Northrend/zone_grizzly_hills.cpp index e71a92b3e0..a59650993d 100644 --- a/src/server/scripts/Northrend/zone_grizzly_hills.cpp +++ b/src/server/scripts/Northrend/zone_grizzly_hills.cpp @@ -102,7 +102,7 @@ public: Talk(SAY_WORGRAGGRO3); if (Creature* RWORG = me->SummonCreature(NPC_RAVENOUS_WORG, me->GetPositionX()+10, me->GetPositionY()+8, me->GetPositionZ()+2, 3.229f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000)) { - RWORG->SetFaction(35); + RWORG->SetFaction(FACTION_FRIENDLY); _RavenousworgGUID = RWORG->GetGUID(); } break; @@ -135,7 +135,7 @@ public: { RWORG->Kill(Mrfloppy); Mrfloppy->ExitVehicle(); - RWORG->SetFaction(14); + RWORG->SetFaction(FACTION_MONSTER); RWORG->GetMotionMaster()->MovePoint(0, RWORG->GetPositionX()+10, RWORG->GetPositionY()+80, RWORG->GetPositionZ()); Talk(SAY_VICTORY2); } diff --git a/src/server/scripts/Northrend/zone_howling_fjord.cpp b/src/server/scripts/Northrend/zone_howling_fjord.cpp index 7fdac43dca..6cfb43f28b 100644 --- a/src/server/scripts/Northrend/zone_howling_fjord.cpp +++ b/src/server/scripts/Northrend/zone_howling_fjord.cpp @@ -41,7 +41,6 @@ EndContentData */ enum Entries { NPC_APOTHECARY_HANES = 23784, - FACTION_ESCORTEE_H = 775, QUEST_TRAIL_OF_FIRE = 11241, SPELL_HEALING_POTION = 17534, @@ -162,7 +161,7 @@ public: break; case EVENT_START_ESCORT: events.Reset(); - me->SetFaction(FACTION_ESCORTEE_H); + me->SetFaction(FACTION_ESCORTEE_H_PASSIVE); me->SetReactState(REACT_AGGRESSIVE); ENSURE_AI(npc_escortAI, (me->AI()))->Start(true, true, _player); break; diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp index 37ce1ea6d6..849a3d5568 100644 --- a/src/server/scripts/Northrend/zone_icecrown.cpp +++ b/src/server/scripts/Northrend/zone_icecrown.cpp @@ -46,7 +46,7 @@ public: { Initialize(); creature->GetMotionMaster()->MovePoint(0, 8599.258f, 963.951f, 547.553f); - creature->SetFaction(35); //wrong faction in db? + creature->SetFaction(FACTION_FRIENDLY); //wrong faction in db? } void Initialize() @@ -68,7 +68,7 @@ public: if (uiType != POINT_MOTION_TYPE) return; - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); } void DamageTaken(Unit* pDoneBy, uint32& uiDamage) override @@ -77,7 +77,7 @@ public: { uiDamage = 0; pDoneBy->CastSpell(pDoneBy, SPELL_KILL_CREDIT, true); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); me->DespawnOrUnsummon(5000); me->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); EnterEvadeMode(); diff --git a/src/server/scripts/Northrend/zone_sholazar_basin.cpp b/src/server/scripts/Northrend/zone_sholazar_basin.cpp index f252a5a68d..1e59badf45 100644 --- a/src/server/scripts/Northrend/zone_sholazar_basin.cpp +++ b/src/server/scripts/Northrend/zone_sholazar_basin.cpp @@ -322,7 +322,7 @@ public: if (npc_engineer_heliceAI* pEscortAI = CAST_AI(npc_engineer_helice::npc_engineer_heliceAI, creature->AI())) { creature->GetMotionMaster()->MoveJumpTo(0, 0.4f, 0.4f); - creature->SetFaction(113); + creature->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); pEscortAI->Start(false, false, player->GetGUID()); creature->AI()->Talk(SAY_WP_1); diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp index b902a0a215..0754ec3fe2 100644 --- a/src/server/scripts/Northrend/zone_storm_peaks.cpp +++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp @@ -90,7 +90,7 @@ public: if (menuId == GOSSIP_ID && gossipListId == GOSSIP_OPTION_ID) { CloseGossipMenuFor(player); - me->SetFaction(113); + me->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); Start(true, true, player->GetGUID()); } } diff --git a/src/server/scripts/Northrend/zone_zuldrak.cpp b/src/server/scripts/Northrend/zone_zuldrak.cpp index a02ab0f128..3335b20e42 100644 --- a/src/server/scripts/Northrend/zone_zuldrak.cpp +++ b/src/server/scripts/Northrend/zone_zuldrak.cpp @@ -135,7 +135,7 @@ public: void Reset() override { - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); DoCast(me, SPELL_KNEEL, true); // Little Hack for kneel - Thanks Illy :P } diff --git a/src/server/scripts/Outland/BlackTemple/black_temple.h b/src/server/scripts/Outland/BlackTemple/black_temple.h index 745038961b..46a134886f 100644 --- a/src/server/scripts/Outland/BlackTemple/black_temple.h +++ b/src/server/scripts/Outland/BlackTemple/black_temple.h @@ -131,7 +131,6 @@ enum BTGameObjectIds enum BlackTempleMisc { - ASHTONGUE_FACTION_FRIEND = 1820, AKAMA_FACTION_COMBAT = 1868, AKAMA_INTRO = 1, AKAMA_FIGHT = 2, diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp index 8fc8c2e2f1..d67317586a 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp @@ -379,7 +379,7 @@ public: void Reset() override { Initialize(); - me->SetFaction(ASHTONGUE_FACTION_FRIEND); + me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN); DoCastSelf(SPELL_STEALTH); if (_instance->GetBossState(DATA_SHADE_OF_AKAMA) != DONE) @@ -425,7 +425,7 @@ public: { _isInCombat = false; me->CombatStop(true); - me->SetFaction(ASHTONGUE_FACTION_FRIEND); + me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN); me->SetWalk(true); _events.Reset(); me->GetMotionMaster()->MovePoint(AKAMA_INTRO_WAYPOINT, AkamaWP[1]); @@ -479,7 +479,7 @@ public: case EVENT_SHADE_CHANNEL: me->SetFacingTo(FACE_THE_PLATFORM); DoCastSelf(SPELL_AKAMA_SOUL_CHANNEL); - me->SetFaction(AKAMA_FACTION_COMBAT); + me->SetFaction(FACTION_MONSTER_SPAR_BUDDY); _events.ScheduleEvent(EVENT_FIXATE, Seconds(5)); break; case EVENT_FIXATE: @@ -527,7 +527,7 @@ public: } } - if (me->GetFaction() == AKAMA_FACTION_COMBAT) + if (me->GetFaction() == FACTION_MONSTER_SPAR_BUDDY) { if (!UpdateVictim()) return; @@ -1165,7 +1165,7 @@ public: Talk(SAY_BROKEN_SPECIAL); break; case ACTION_BROKEN_HAIL: - me->SetFaction(ASHTONGUE_FACTION_FRIEND); + me->SetFaction(FACTION_ASHTONGUE_DEATHSWORN); Talk(SAY_BROKEN_HAIL); break; case ACTION_BROKEN_EMOTE: diff --git a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp index 7fc4cc76a0..a12d920736 100644 --- a/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp +++ b/src/server/scripts/Outland/BlackTemple/instance_black_temple.cpp @@ -123,7 +123,7 @@ class instance_black_temple : public InstanceMapScript case NPC_STORM_FURY: AshtongueGUIDs.emplace_back(creature->GetGUID()); if (GetBossState(DATA_SHADE_OF_AKAMA) == DONE) - creature->SetFaction(ASHTONGUE_FACTION_FRIEND); + creature->SetFaction(FACTION_ASHTONGUE_DEATHSWORN); break; default: break; @@ -170,7 +170,7 @@ class instance_black_temple : public InstanceMapScript if (state == DONE) for (ObjectGuid ashtongueGuid : AshtongueGUIDs) if (Creature* ashtongue = instance->GetCreature(ashtongueGuid)) - ashtongue->SetFaction(ASHTONGUE_FACTION_FRIEND); + ashtongue->SetFaction(FACTION_ASHTONGUE_DEATHSWORN); // no break case DATA_TERON_GOREFIEND: case DATA_GURTOGG_BLOODBOIL: diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index aa88010319..815aec6ed2 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -754,7 +754,7 @@ public: void Reset() override { me->SetDisableGravity(true); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); Initialize(); } @@ -789,7 +789,7 @@ public: { if (Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) { - trig->SetFaction(14); + trig->SetFaction(FACTION_MONSTER); trig->CastSpell(trig, SPELL_TOXIC_SPORES, true); } } @@ -807,7 +807,7 @@ public: // remove me->setDeathState(DEAD); me->RemoveCorpse(); - me->SetFaction(35); + me->SetFaction(FACTION_FRIENDLY); } CheckTimer = 1000; diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp index 3e5ee17b86..8640213703 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp @@ -319,7 +319,7 @@ public: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); } void EnterCombat(Unit* /*who*/) override { } diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp index 45a863886d..2bf0b1870f 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp @@ -206,7 +206,7 @@ class boss_grand_warlock_nethekurse : public CreatureScript void JustSummoned(Creature* summoned) override { - summoned->SetFaction(16); + summoned->SetFaction(FACTION_MONSTER_2); summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 12928ccc76..0ded5aa409 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -1277,7 +1277,7 @@ class npc_kael_flamestrike : public CreatureScript Initialize(); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFaction(14); + me->SetFaction(FACTION_MONSTER); } void MoveInLineOfSight(Unit* /*who*/) override { } diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp index 0d4c615d97..6c469601ef 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp @@ -538,7 +538,7 @@ class npc_zerekethvoidzone : public CreatureScript void Reset() override { me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); - me->SetFaction(16); + me->SetFaction(FACTION_MONSTER_2); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_VOID_ZONE_DAMAGE); diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index a3fc6ecb8d..d15e358376 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -45,8 +45,6 @@ enum Aeranas { SAY_SUMMON = 0, SAY_FREE = 1, - FACTION_HOSTILE = 16, - FACTION_FRIENDLY = 35, SPELL_ENVELOPING_WINDS = 15535, SPELL_SHOCK = 12553 }; @@ -86,7 +84,7 @@ public: { if (faction_Timer <= diff) { - me->SetFaction(FACTION_HOSTILE); + me->SetFaction(FACTION_MONSTER_2); faction_Timer = 0; } else faction_Timer -= diff; } @@ -250,8 +248,7 @@ enum WoundedBloodElf SAY_ELF_AGGRO = 5, QUEST_ROAD_TO_FALCON_WATCH = 9375, NPC_HAALESHI_WINDWALKER = 16966, - NPC_HAALESHI_TALONGUARD = 16967, - FACTION_FALCON_WATCH_QUEST = 775 + NPC_HAALESHI_TALONGUARD = 16967 }; class npc_wounded_blood_elf : public CreatureScript @@ -280,7 +277,7 @@ public: { if (quest->GetQuestId() == QUEST_ROAD_TO_FALCON_WATCH) { - me->SetFaction(FACTION_FALCON_WATCH_QUEST); + me->SetFaction(FACTION_ESCORTEE_H_PASSIVE); npc_escortAI::Start(true, false, player->GetGUID()); } } @@ -1003,7 +1000,7 @@ public: break; case EVENT_ATTACK: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); - me->SetFaction(FACTION_HOSTILE); + me->SetFaction(FACTION_MONSTER_2); me->CombatStart(ObjectAccessor::GetPlayer(*me, _playerGUID)); _events.ScheduleEvent(EVENT_FIREBALL, 1); _events.ScheduleEvent(EVENT_FROSTNOVA, Seconds(5)); diff --git a/src/server/scripts/Outland/zone_nagrand.cpp b/src/server/scripts/Outland/zone_nagrand.cpp index 98c3433cbd..fd53ec8ba0 100644 --- a/src/server/scripts/Outland/zone_nagrand.cpp +++ b/src/server/scripts/Outland/zone_nagrand.cpp @@ -76,7 +76,7 @@ public: if (npc_maghar_captiveAI* EscortAI = dynamic_cast(creature->AI())) { creature->SetStandState(UNIT_STAND_STATE_STAND); - creature->SetFaction(232); + creature->SetFaction(FACTION_ESCORTEE_H_NEUTRAL_ACTIVE); EscortAI->Start(true, false, player->GetGUID(), quest); creature->AI()->Talk(SAY_MAG_START); @@ -430,7 +430,7 @@ public: if (npc_kurenai_captiveAI* EscortAI = dynamic_cast(creature->AI())) { creature->SetStandState(UNIT_STAND_STATE_STAND); - creature->SetFaction(231); + creature->SetFaction(FACTION_ESCORTEE_A_NEUTRAL_ACTIVE); EscortAI->Start(true, false, player->GetGUID(), quest); creature->AI()->Talk(SAY_KUR_START); diff --git a/src/server/scripts/Outland/zone_netherstorm.cpp b/src/server/scripts/Outland/zone_netherstorm.cpp index 82334302da..4f2eccd751 100644 --- a/src/server/scripts/Outland/zone_netherstorm.cpp +++ b/src/server/scripts/Outland/zone_netherstorm.cpp @@ -496,7 +496,7 @@ public: { if (quest->GetQuestId() == Q_ALMABTRIEB) { - creature->SetFaction(113); + creature->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); ENSURE_AI(npc_escortAI, (creature->AI()))->Start(true, false, player->GetGUID()); } @@ -662,7 +662,7 @@ public: { if (npc_maxx_a_million_escortAI* pEscortAI = CAST_AI(npc_maxx_a_million_escort::npc_maxx_a_million_escortAI, creature->AI())) { - creature->SetFaction(113); + creature->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); pEscortAI->Start(false, false, player->GetGUID()); } } diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index ac57498ec1..b248b0cced 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -336,10 +336,6 @@ public: enum EnshlavedNetherwingDrake { - // Factions - FACTION_DEFAULT = 62, - FACTION_FRIENDLY = 1840, // Not sure if this is correct, it was taken off of Mordenai. - // Spells SPELL_HIT_FORCE_OF_NELTHARAKU = 38762, SPELL_FORCE_OF_NELTHARAKU = 38775, @@ -375,7 +371,7 @@ public: void Reset() override { if (!Tapped) - me->SetFaction(FACTION_DEFAULT); + me->SetFaction(FACTION_ORC_DRAGONMAW); FlyTimer = 10000; me->SetDisableGravity(false); @@ -392,7 +388,7 @@ public: Tapped = true; PlayerGUID = caster->GetGUID(); - me->SetFaction(FACTION_FRIENDLY); + me->SetFaction(FACTION_FLAYER_HUNTER); DoCast(caster, SPELL_FORCE_OF_NELTHARAKU, true); Unit* Dragonmaw = me->FindNearestCreature(NPC_DRAGONMAW_SUBJUGATOR, 50); @@ -587,8 +583,7 @@ enum Earthmender SPELL_HEALING_WAVE = 12491, QUEST_ESCAPE_COILSCAR = 10451, - NPC_COILSKAR_ASSASSIN = 21044, - FACTION_EARTHEN = 1726 //guessed + NPC_COILSKAR_ASSASSIN = 21044 }; class npc_earthmender_wilda : public CreatureScript @@ -601,7 +596,7 @@ public: if (quest->GetQuestId() == QUEST_ESCAPE_COILSCAR) { creature->AI()->Talk(SAY_WIL_START, player); - creature->SetFaction(FACTION_EARTHEN); + creature->SetFaction(FACTION_EARTHEN_RING); if (npc_earthmender_wildaAI* pEscortAI = CAST_AI(npc_earthmender_wilda::npc_earthmender_wildaAI, creature->AI())) pEscortAI->Start(false, false, player->GetGUID(), quest); @@ -1407,11 +1402,7 @@ enum Enraged_Dpirits NPC_CREDIT_EARTH = 21092, // Captured Spell / Buff - SPELL_SOUL_CAPTURED = 36115, - - // Factions - FACTION_ENRAGED_SOUL_FRIENDLY = 35, - FACTION_ENRAGED_SOUL_HOSTILE = 14 + SPELL_SOUL_CAPTURED = 36115 }; class npc_enraged_spirit : public CreatureScript @@ -1479,7 +1470,7 @@ public: totemOspirits = me->FindNearestCreature(ENTRY_TOTEM_OF_SPIRITS, RADIUS_TOTEM_OF_SPIRITS); if (totemOspirits) { - Summoned->SetFaction(FACTION_ENRAGED_SOUL_FRIENDLY); + Summoned->SetFaction(FACTION_FRIENDLY); Summoned->GetMotionMaster()->MovePoint(0, totemOspirits->GetPositionX(), totemOspirits->GetPositionY(), Summoned->GetPositionZ()); if (Unit* owner = totemOspirits->GetOwner()) diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp index 01c88a427f..b567d4e310 100644 --- a/src/server/scripts/Outland/zone_shattrath_city.cpp +++ b/src/server/scripts/Outland/zone_shattrath_city.cpp @@ -46,7 +46,6 @@ enum RaliqTheDrunk { SAY_RALIQ_ATTACK = 0, OPTION_ID_COLLECT_A_DEBT = 0, - FACTION_OGRE_HOSTILE = 45, MENU_ID_COLLECT_A_DEBT = 7729, NPC_TEXT_WUT_YOU_WANT = 9440, CRACKIN_SOME_SKULLS = 10009, @@ -64,7 +63,7 @@ public: if (action == GOSSIP_ACTION_INFO_DEF+1) { CloseGossipMenuFor(player); - creature->SetFaction(FACTION_OGRE_HOSTILE); + creature->SetFaction(FACTION_OGRE); creature->AI()->Talk(SAY_RALIQ_ATTACK, player); creature->AI()->AttackStart(player); } @@ -135,8 +134,6 @@ enum Salsalabim { SAY_DEMONIC_AGGRO = 0, OPTION_ID_ALTRUIS_SENT_ME = 0, - FACTION_FRIENDLY = 35, - FACTION_DEMON_HOSTILE = 90, MENU_ID_ALTRUIS_SENT_ME = 7725, NPC_TEXT_SAL_GROWLS_AT_YOU = 9435, PATIENCE_AND_UNDERSTANDING = 10004, @@ -154,7 +151,7 @@ public: if (action == GOSSIP_ACTION_INFO_DEF+1) { CloseGossipMenuFor(player); - creature->SetFaction(FACTION_DEMON_HOSTILE); + creature->SetFaction(FACTION_DEMON); creature->AI()->Talk(SAY_DEMONIC_AGGRO, player); creature->AI()->AttackStart(player); } diff --git a/src/server/scripts/Outland/zone_terokkar_forest.cpp b/src/server/scripts/Outland/zone_terokkar_forest.cpp index 5ce305b426..cce88ab584 100644 --- a/src/server/scripts/Outland/zone_terokkar_forest.cpp +++ b/src/server/scripts/Outland/zone_terokkar_forest.cpp @@ -48,8 +48,6 @@ enum UnkorTheRuthless { SAY_SUBMIT = 0, REQUIRED_KILL_COUNT = 10, - FACTION_FRIENDLY = 35, - FACTION_HOSTILE = 45, SPELL_PULVERIZE = 2676, QUEST_DONTKILLTHEFATONE = 9889, NPC_BOULDERFIST_INVADER = 18260 @@ -87,7 +85,7 @@ public: { Initialize(); me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetFaction(FACTION_HOSTILE); + me->SetFaction(FACTION_OGRE); } void EnterCombat(Unit* /*who*/) override { } @@ -310,7 +308,6 @@ enum Floon SAY_FLOON_ATTACK = 0, OPTION_ID_PAY_UP_OR_DIE = 0, OPTION_ID_COLLECT_A_DEBT = 0, - FACTION_HOSTILE_FLOON = 1738, MENU_ID_PAY_UP_OR_DIE = 7731, MENU_ID_COLLECT_A_DEBT = 7732, GOSSIP_FLOON_STRANGE_SOUNDS = 9442, @@ -339,7 +336,7 @@ public: if (action == GOSSIP_ACTION_INFO_DEF+1) { CloseGossipMenuFor(player); - creature->SetFaction(FACTION_HOSTILE_FLOON); + creature->SetFaction(FACTION_ARAKKOA); creature->AI()->Talk(SAY_FLOON_ATTACK, player); creature->AI()->AttackStart(player); } @@ -427,7 +424,6 @@ enum IslaStarmaneData SAY_PROGRESS_3 = 2, SAY_PROGRESS_4 = 3, GO_DISTANCE = 10, - FACTION_ESCORTEE = 113, ESCAPE_FROM_FIREWING_POINT_A = 10051, ESCAPE_FROM_FIREWING_POINT_H = 10052, SPELL_TRAVEL_FORM_CAT = 32447, @@ -504,7 +500,7 @@ public: if (quest->GetQuestId() == ESCAPE_FROM_FIREWING_POINT_H || quest->GetQuestId() == ESCAPE_FROM_FIREWING_POINT_A) { ENSURE_AI(npc_escortAI, (creature->AI()))->Start(true, false, player->GetGUID()); - creature->SetFaction(FACTION_ESCORTEE); + creature->SetFaction(FACTION_ESCORTEE_N_NEUTRAL_PASSIVE); } return true; } @@ -644,9 +640,9 @@ public: pEscortAI->Start(false, false, player->GetGUID()); if (player->GetTeamId() == TEAM_ALLIANCE) - creature->SetFaction(FACTION_ESCORT_A_NEUTRAL_PASSIVE); + creature->SetFaction(FACTION_ESCORTEE_A_NEUTRAL_PASSIVE); else - creature->SetFaction(FACTION_ESCORT_H_NEUTRAL_PASSIVE); + creature->SetFaction(FACTION_ESCORTEE_H_NEUTRAL_PASSIVE); } return true; } diff --git a/src/server/scripts/Outland/zone_zangarmarsh.cpp b/src/server/scripts/Outland/zone_zangarmarsh.cpp index f6cc09eba8..b5b0e21362 100644 --- a/src/server/scripts/Outland/zone_zangarmarsh.cpp +++ b/src/server/scripts/Outland/zone_zangarmarsh.cpp @@ -158,8 +158,7 @@ public: enum Cooshhooosh { SPELL_LIGHTNING_BOLT = 9532, - QUEST_CRACK_SKULLS = 10009, - FACTION_HOSTILE_CO = 45 + QUEST_CRACK_SKULLS = 10009 }; class npc_cooshcoosh : public CreatureScript @@ -227,7 +226,7 @@ public: if (action == GOSSIP_ACTION_INFO_DEF) { CloseGossipMenuFor(player); - creature->SetFaction(FACTION_HOSTILE_CO); + creature->SetFaction(FACTION_OGRE); creature->AI()->AttackStart(player); } return true; diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index 3503ee7829..8d7966edf4 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -3741,7 +3741,7 @@ class spell_gen_gm_freeze : public SpellScriptLoader if (Player* player = GetTarget()->ToPlayer()) { // stop combat + make player unattackable + duel stop + stop some spells - player->SetFaction(35); + player->SetFaction(FACTION_FRIENDLY); player->CombatStop(); if (player->IsNonMeleeSpellCast(true)) player->InterruptNonMeleeSpells(true); diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index cd33620fba..486df91a93 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -256,9 +256,7 @@ enum ChickenCluck EMOTE_HELLO_H = 1, EMOTE_CLUCK_TEXT = 2, - QUEST_CLUCK = 3861, - FACTION_FRIENDLY = 35, - FACTION_CHICKEN = 31 + QUEST_CLUCK = 3861 }; class npc_chicken_cluck : public CreatureScript @@ -283,7 +281,7 @@ public: void Reset() override { Initialize(); - me->SetFaction(FACTION_CHICKEN); + me->SetFaction(FACTION_PREY); me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); } diff --git a/src/server/worldserver/CommandLine/CliRunnable.cpp b/src/server/worldserver/CommandLine/CliRunnable.cpp index 633cde6a9a..d5e03edbd0 100644 --- a/src/server/worldserver/CommandLine/CliRunnable.cpp +++ b/src/server/worldserver/CommandLine/CliRunnable.cpp @@ -29,7 +29,7 @@ #include "Log.h" #include "Util.h" -#if PLATFORM != PLATFORM_WINDOWS +#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS #include #include #include "Chat.h" @@ -86,7 +86,7 @@ int cli_hook_func() void utf8print(void* /*arg*/, const char* str) { -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS wchar_t wtemp_buf[6000]; size_t wtemp_len = 6000-1; if (!Utf8toWStr(str, strlen(str), wtemp_buf, wtemp_len)) @@ -129,7 +129,7 @@ void CliThread() { ///- Display the list of available CLI functions then beep //TC_LOG_INFO("server.worldserver", ""); -#if PLATFORM != PLATFORM_WINDOWS +#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS rl_attempted_completion_function = cli_completion; rl_event_hook = cli_hook_func; #endif @@ -148,7 +148,7 @@ void CliThread() char *command_str ; // = fgets(commandbuf, sizeof(commandbuf), stdin); -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS char commandbuf[256]; command_str = fgets(commandbuf, sizeof(commandbuf), stdin); #else @@ -167,7 +167,7 @@ void CliThread() if (!*command_str) { -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS printf("TC>"); #else free(command_str); @@ -178,7 +178,7 @@ void CliThread() std::string command; if (!consoleToUtf8(command_str, command)) // convert from console encoding to utf8 { -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS printf("TC>"); #else free(command_str); @@ -188,7 +188,7 @@ void CliThread() fflush(stdout); sWorld->QueueCliCommand(new CliCommandHolder(NULL, command.c_str(), &utf8print, &commandFinished)); -#if PLATFORM != PLATFORM_WINDOWS +#if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS add_history(command.c_str()); free(command_str); #endif diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index ee12a09342..a45b09a1de 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -47,6 +47,7 @@ #include "BattlenetServerManager.h" #include "DatabaseLoader.h" #include "AppenderDB.h" +#include "Metric.h" #include #include #include @@ -167,7 +168,7 @@ extern int main(int argc, char** argv) // Set signal handlers (this must be done before starting io_service threads, because otherwise they would unblock and exit) boost::asio::signal_set signals(_ioService, SIGINT, SIGTERM); -#if PLATFORM == PLATFORM_WINDOWS +#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS signals.add(SIGBREAK); #endif signals.async_wait(SignalHandler); @@ -197,6 +198,13 @@ extern int main(int argc, char** argv) LoadRealmInfo(); + sMetric->Initialize(realm.Name, _ioService, []() + { + TC_METRIC_VALUE("online_players", sWorld->GetPlayerCount()); + }); + + TC_METRIC_EVENT("events", "Worldserver started", ""); + // Initialize the World sScriptMgr->SetScriptLoader(AddScripts); sWorld->SetInitialWorldSettings(); @@ -233,7 +241,7 @@ extern int main(int argc, char** argv) if (networkThreads <= 0) { TC_LOG_ERROR("server.worldserver", "Network.Threads must be greater than 0"); - return false; + return 1; } sWorldSocketMgr.StartNetwork(_ioService, worldListener, worldPort, networkThreads); @@ -304,6 +312,9 @@ extern int main(int argc, char** argv) StopDB(); + TC_METRIC_EVENT("events", "Worldserver shutdown", ""); + sMetric->ForceSend(); + TC_LOG_INFO("server.worldserver", "Halting process..."); ShutdownCLIThread(cliThread); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 1d0b111734..8ee38cacef 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -35,6 +35,7 @@ # LOGGING SYSTEM SETTINGS # CURRENCIES SETTINGS # PACKET SPOOF PROTECTION SETTINGS +# METRIC SETTINGS # ################################################################################################### @@ -3960,3 +3961,41 @@ BnetServer.Port = 1118 # ################################################################################################### + +################################################################################################### +# METRIC SETTINGS +# +# These settings control the statistics sent to the metric database (currently InfluxDB) +# +# Metric.Enable +# Description: Enables statistics sent to the metric database. +# Default: 0 - (Disabled) +# 1 - (Enabled) + +Metric.Enable = 0 + +# +# Metric.Interval +# Description: Interval between every batch of data sent in seconds +# Default: 10 seconds +# + +Metric.Interval = 10 + +# +# Metric.ConnectionInfo +# Description: Connection settings for metric database (currently InfluxDB). +# Example: "hostname;port;database" +# Default: "127.0.0.1;8086;worldserver" + +Metric.ConnectionInfo = "127.0.0.1;8086;worldserver" + +# +# Metric.OverallStatusInterval +# Description: Interval between every gathering of overall worldserver status data in seconds +# Default: 1 second +# + +Metric.OverallStatusInterval = 1 + +################################################################################################### \ No newline at end of file