| 608 | | //***Preform all DB queries here*** |
| 609 | | QueryResult *result; |
| 610 | | |
| 611 | | //Get Version information |
| 612 | | result = TScriptDB.PQuery("SELECT `version`" |
| 613 | | "FROM `script_db_version`"); |
| 614 | | |
| 615 | | if (result) |
| | 610 | error_log("TSCR: Unable to connect to Database. Load database aborted."); |
| | 611 | return; |
| | 612 | } |
| | 613 | |
| | 614 | //***Preform all DB queries here*** |
| | 615 | QueryResult *result; |
| | 616 | |
| | 617 | //Get Version information |
| | 618 | result = TScriptDB.PQuery("SELECT version FROM script_db_version"); |
| | 619 | |
| | 620 | if (result) |
| | 621 | { |
| | 622 | Field *fields = result->Fetch(); |
| | 623 | outstring_log("TSCR: Database version is: %s", fields[0].GetString()); |
| | 624 | outstring_log(""); |
| | 625 | delete result; |
| | 626 | |
| | 627 | }else |
| | 628 | { |
| | 629 | error_log("TSCR: Missing `script_db_version` information."); |
| | 630 | outstring_log(""); |
| | 631 | } |
| | 632 | |
| | 633 | // Drop Existing Text Map, only done once and we are ready to add data from multiple sources. |
| | 634 | TextMap.clear(); |
| | 635 | |
| | 636 | //TODO: Add load from eventai_texts here |
| | 637 | |
| | 638 | // Load Script Text |
| | 639 | outstring_log("TSCR: Loading Script Texts..."); |
| | 640 | LoadMangosStrings(TScriptDB,"script_texts",TEXT_SOURCE_RANGE,(TEXT_SOURCE_RANGE*2)+1); |
| | 641 | |
| | 642 | // Gather Additional data from Script Texts |
| | 643 | result = TScriptDB.PQuery("SELECT entry, sound, type, language FROM script_texts"); |
| | 644 | |
| | 645 | outstring_log("TSCR: Loading Script Texts additional data..."); |
| | 646 | if (result) |
| | 647 | { |
| | 648 | barGoLink bar(result->GetRowCount()); |
| | 649 | uint32 count = 0; |
| | 650 | |
| | 651 | do |
| | 653 | bar.step(); |
| | 654 | Field* fields = result->Fetch(); |
| | 655 | StringTextData temp; |
| | 656 | |
| | 657 | int32 i = fields[0].GetInt32(); |
| | 658 | temp.SoundId = fields[1].GetInt32(); |
| | 659 | temp.Type = fields[2].GetInt32(); |
| | 660 | temp.Language = fields[3].GetInt32(); |
| | 661 | |
| | 662 | if (i >= 0) |
| | 663 | { |
| | 664 | error_db_log("TSCR: Entry %i in table `script_texts` is not a negative value.",i); |
| | 665 | continue; |
| | 666 | } |
| | 667 | |
| | 668 | if (i > TEXT_SOURCE_RANGE || i <= TEXT_SOURCE_RANGE*2) |
| | 669 | { |
| | 670 | error_db_log("TSCR: Entry %i in table `script_texts` is out of accepted entry range for table.",i); |
| | 671 | continue; |
| | 672 | } |
| | 673 | |
| | 674 | if (temp.SoundId) |
| | 675 | { |
| | 676 | if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId)) |
| | 677 | error_db_log("TSCR: Entry %i in table `script_texts` has soundId %u but sound does not exist.",i,temp.SoundId); |
| | 678 | } |
| | 679 | |
| | 680 | if (!GetLanguageDescByID(temp.Language)) |
| | 681 | error_db_log("TSCR: Entry %i in table `script_texts` using Language %u but Language does not exist.",i,temp.Language); |
| | 682 | |
| | 683 | if (temp.Type > CHAT_TYPE_BOSS_WHISPER) |
| | 684 | error_db_log("TSCR: Entry %i in table `script_texts` has Type %u but this Chat Type does not exist.",i,temp.Type); |
| | 685 | |
| | 686 | TextMap[i] = temp; |
| | 687 | ++count; |
| | 688 | } while (result->NextRow()); |
| | 689 | |
| | 690 | delete result; |
| | 691 | |
| | 692 | outstring_log(""); |
| | 693 | outstring_log(">> TSCR: Loaded %u additional Script Texts data.", count); |
| | 694 | }else |
| | 695 | { |
| | 696 | barGoLink bar(1); |
| | 697 | bar.step(); |
| | 698 | outstring_log(""); |
| | 699 | outstring_log(">> Loaded 0 additional Script Texts data. DB table `script_texts` is empty."); |
| | 700 | } |
| | 701 | |
| | 702 | // Load Custom Text |
| | 703 | outstring_log("TSCR: Loading Custom Texts..."); |
| | 704 | LoadMangosStrings(TScriptDB,"custom_texts",TEXT_SOURCE_RANGE*2,(TEXT_SOURCE_RANGE*3)+1); |
| | 705 | |
| | 706 | // Gather Additional data from Custom Texts |
| | 707 | result = TScriptDB.PQuery("SELECT entry, sound, type, language FROM custom_texts"); |
| | 708 | |
| | 709 | outstring_log("TSCR: Loading Custom Texts additional data..."); |
| | 710 | if (result) |
| | 711 | { |
| | 712 | barGoLink bar(result->GetRowCount()); |
| | 713 | uint32 count = 0; |
| | 714 | |
| | 715 | do |
| | 716 | { |
| | 717 | bar.step(); |
| | 718 | Field* fields = result->Fetch(); |
| | 719 | StringTextData temp; |
| | 720 | |
| | 721 | int32 i = fields[0].GetInt32(); |
| | 722 | temp.SoundId = fields[1].GetInt32(); |
| | 723 | temp.Type = fields[2].GetInt32(); |
| | 724 | temp.Language = fields[3].GetInt32(); |
| | 725 | |
| | 726 | if (i >= 0) |
| | 727 | { |
| | 728 | error_db_log("TSCR: Entry %i in table `custom_texts` is not a negative value.",i); |
| | 729 | continue; |
| | 730 | } |
| | 731 | |
| | 732 | if (i > TEXT_SOURCE_RANGE*2 || i <= TEXT_SOURCE_RANGE*3) |
| | 733 | { |
| | 734 | error_db_log("TSCR: Entry %i in table `custom_texts` is out of accepted entry range for table.",i); |
| | 735 | continue; |
| | 736 | } |
| | 737 | |
| | 738 | if (temp.SoundId) |
| | 739 | { |
| | 740 | if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId)) |
| | 741 | error_db_log("TSCR: Entry %i in table `custom_texts` has soundId %u but sound does not exist.",i,temp.SoundId); |
| | 742 | } |
| | 743 | |
| | 744 | if (!GetLanguageDescByID(temp.Language)) |
| | 745 | error_db_log("TSCR: Entry %i in table `custom_texts` using Language %u but Language does not exist.",i,temp.Language); |
| | 746 | |
| | 747 | if (temp.Type > CHAT_TYPE_BOSS_WHISPER) |
| | 748 | error_db_log("TSCR: Entry %i in table `custom_texts` has Type %u but this Chat Type does not exist.",i,temp.Type); |
| | 749 | |
| | 750 | TextMap[i] = temp; |
| | 751 | ++count; |
| | 752 | } while (result->NextRow()); |
| | 753 | |
| | 754 | delete result; |
| | 755 | |
| | 756 | outstring_log(""); |
| | 757 | outstring_log(">> Loaded %u additional Custom Texts data.", count); |
| | 758 | }else |
| | 759 | { |
| | 760 | barGoLink bar(1); |
| | 761 | bar.step(); |
| | 762 | outstring_log(""); |
| | 763 | outstring_log(">> Loaded 0 additional Custom Texts data. DB table `custom_texts` is empty."); |
| | 764 | } |
| | 765 | |
| | 766 | // Drop existing Event AI Localized Text hash map |
| | 767 | EventAI_LocalizedTextMap.clear(); |
| | 768 | |
| | 769 | // Gather EventAI Localized Texts |
| | 770 | result = TScriptDB.PQuery("SELECT id, locale_1, locale_2, locale_3, locale_4, locale_5, locale_6, locale_7, locale_8 " |
| | 771 | "FROM eventai_localized_texts"); |
| | 772 | |
| | 773 | outstring_log("TSCR: Loading EventAI Localized Texts..."); |
| | 774 | if(result) |
| | 775 | { |
| | 776 | barGoLink bar(result->GetRowCount()); |
| | 777 | uint32 count = 0; |
| | 778 | |
| | 779 | do |
| | 780 | { |
| | 781 | Localized_Text temp; |
| | 782 | bar.step(); |
| | 783 | |
| 618 | | outstring_log(" "); |
| 619 | | outstring_log("TSCR: Database version is: %s", fields[0].GetString()); |
| 620 | | outstring_log(" "); |
| 621 | | delete result; |
| 622 | | |
| 623 | | }else error_db_log("TSCR: Missing script_db_version information."); |
| 624 | | |
| 625 | | // Drop existing Event AI Localized Text hash map |
| 626 | | EventAI_LocalizedTextMap.clear(); |
| 627 | | |
| 628 | | // Gather EventAI Localized Texts |
| 629 | | result = TScriptDB.PQuery("SELECT `id`,`locale_1`,`locale_2`,`locale_3`,`locale_4`,`locale_5`,`locale_6`,`locale_7`,`locale_8`" |
| 630 | | "FROM `eventai_localized_texts`"); |
| 631 | | |
| 632 | | if(result) |
| | 785 | |
| | 786 | uint32 i = fields[0].GetInt32(); |
| | 787 | |
| | 788 | temp.locale_1 = fields[1].GetString(); |
| | 789 | temp.locale_2 = fields[2].GetString(); |
| | 790 | temp.locale_3 = fields[3].GetString(); |
| | 791 | temp.locale_4 = fields[4].GetString(); |
| | 792 | temp.locale_5 = fields[5].GetString(); |
| | 793 | temp.locale_6 = fields[6].GetString(); |
| | 794 | temp.locale_7 = fields[7].GetString(); |
| | 795 | temp.locale_8 = fields[8].GetString(); |
| | 796 | |
| | 797 | EventAI_LocalizedTextMap[i] = temp; |
| | 798 | ++count; |
| | 799 | |
| | 800 | }while(result->NextRow()); |
| | 801 | |
| | 802 | delete result; |
| | 803 | |
| | 804 | outstring_log(""); |
| | 805 | outstring_log(">> Loaded %u EventAI Localized Texts", count); |
| | 806 | }else |
| | 807 | { |
| | 808 | barGoLink bar(1); |
| | 809 | bar.step(); |
| | 810 | outstring_log(""); |
| | 811 | outstring_log(">> Loaded 0 EventAI Localized Texts. DB table `eventai_localized_texts` is empty"); |
| | 812 | } |
| | 813 | |
| | 814 | //Drop existing EventAI Text hash map |
| | 815 | EventAI_Text_Map.clear(); |
| | 816 | |
| | 817 | //Gather EventAI Text Entries |
| | 818 | result = TScriptDB.PQuery("SELECT id, text FROM eventai_texts"); |
| | 819 | |
| | 820 | outstring_log("TSCR: Loading EventAI_Texts..."); |
| | 821 | if (result) |
| | 822 | { |
| | 823 | barGoLink bar(result->GetRowCount()); |
| | 824 | uint32 Count = 0; |
| | 825 | |
| | 826 | do |
| 634 | | outstring_log("TSCR: Loading EAI Localized Texts...."); |
| 635 | | barGoLink bar(result->GetRowCount()); |
| 636 | | uint32 count = 0; |
| 637 | | |
| 638 | | do |
| | 828 | bar.step(); |
| | 829 | Field *fields = result->Fetch(); |
| | 830 | |
| | 831 | uint32 i = fields[0].GetInt32(); |
| | 832 | |
| | 833 | std::string text = fields[1].GetString(); |
| | 834 | |
| | 835 | if (!strlen(text.c_str())) |
| | 836 | error_db_log("TSCR: EventAI text %u is empty", i); |
| | 837 | |
| | 838 | EventAI_Text_Map[i] = text; |
| | 839 | ++Count; |
| | 840 | |
| | 841 | }while (result->NextRow()); |
| | 842 | |
| | 843 | delete result; |
| | 844 | |
| | 845 | outstring_log(""); |
| | 846 | outstring_log(">> Loaded %u EventAI texts", Count); |
| | 847 | }else |
| | 848 | { |
| | 849 | barGoLink bar(1); |
| | 850 | bar.step(); |
| | 851 | outstring_log(""); |
| | 852 | outstring_log(">> Loaded 0 EventAI texts. DB table `eventai_texts` is empty."); |
| | 853 | } |
| | 854 | |
| | 855 | //Gather event data |
| | 856 | result = TScriptDB.PQuery("SELECT id, position_x, position_y, position_z, orientation, spawntimesecs FROM eventai_summons"); |
| | 857 | |
| | 858 | //Drop Existing EventSummon Map |
| | 859 | EventAI_Summon_Map.clear(); |
| | 860 | |
| | 861 | outstring_log("TSCR: Loading EventAI_Summons..."); |
| | 862 | if (result) |
| | 863 | { |
| | 864 | barGoLink bar(result->GetRowCount()); |
| | 865 | uint32 Count = 0; |
| | 866 | |
| | 867 | do |
| | 868 | { |
| | 869 | bar.step(); |
| | 870 | Field *fields = result->Fetch(); |
| | 871 | |
| | 872 | EventAI_Summon temp; |
| | 873 | |
| | 874 | uint32 i = fields[0].GetUInt32(); |
| | 875 | temp.position_x = fields[1].GetFloat(); |
| | 876 | temp.position_y = fields[2].GetFloat(); |
| | 877 | temp.position_z = fields[3].GetFloat(); |
| | 878 | temp.orientation = fields[4].GetFloat(); |
| | 879 | temp.SpawnTimeSecs = fields[5].GetUInt32(); |
| | 880 | |
| | 881 | //Add to map |
| | 882 | EventAI_Summon_Map[i] = temp; |
| | 883 | ++Count; |
| | 884 | }while (result->NextRow()); |
| | 885 | |
| | 886 | delete result; |
| | 887 | |
| | 888 | outstring_log(""); |
| | 889 | outstring_log(">> Loaded %u EventAI summon definitions", Count); |
| | 890 | }else |
| | 891 | { |
| | 892 | barGoLink bar(1); |
| | 893 | bar.step(); |
| | 894 | outstring_log(""); |
| | 895 | outstring_log(">> Loaded 0 EventAI Summon definitions. DB table `eventai_summons` is empty."); |
| | 896 | } |
| | 897 | |
| | 898 | //Gather event data |
| | 899 | result = TScriptDB.PQuery("SELECT id, creature_id, event_type, event_inverse_phase_mask, event_chance, event_flags, " |
| | 900 | "event_param1, event_param2, event_param3, event_param4, " |
| | 901 | "action1_type, action1_param1, action1_param2, action1_param3, " |
| | 902 | "action2_type, action2_param1, action2_param2, action2_param3, " |
| | 903 | "action3_type, action3_param1, action3_param2, action3_param3 " |
| | 904 | "FROM eventai_scripts"); |
| | 905 | |
| | 906 | //Drop Existing EventAI List |
| | 907 | EventAI_Event_List.clear(); |
| | 908 | |
| | 909 | outstring_log("TSCR: Loading EventAI_Scripts..."); |
| | 910 | if (result) |
| | 911 | { |
| | 912 | barGoLink bar(result->GetRowCount()); |
| | 913 | uint32 Count = 0; |
| | 914 | |
| | 915 | do |
| | 916 | { |
| | 917 | bar.step(); |
| | 918 | Field *fields = result->Fetch(); |
| | 919 | |
| | 920 | EventAI_Event temp; |
| | 921 | |
| | 922 | temp.event_id = fields[0].GetUInt32(); |
| | 923 | uint32 i = temp.event_id; |
| | 924 | temp.creature_id = fields[1].GetUInt32(); |
| | 925 | temp.event_type = fields[2].GetUInt16(); |
| | 926 | temp.event_inverse_phase_mask = fields[3].GetUInt32(); |
| | 927 | temp.event_chance = fields[4].GetUInt8(); |
| | 928 | temp.event_flags = fields[5].GetUInt8(); |
| | 929 | temp.event_param1 = fields[6].GetUInt32(); |
| | 930 | temp.event_param2 = fields[7].GetUInt32(); |
| | 931 | temp.event_param3 = fields[8].GetUInt32(); |
| | 932 | temp.event_param4 = fields[9].GetUInt32(); |
| | 933 | |
| | 934 | //Report any errors in event |
| | 935 | if (temp.event_type >= EVENT_T_END) |
| | 936 | error_db_log("TSCR: Event %u has incorrect event type. Maybe DB requires updated version of SD2.", i); |
| | 937 | |
| | 938 | //No chance of this event occuring |
| | 939 | if (temp.event_chance == 0) |
| | 940 | error_db_log("TSCR: Event %u has 0 percent chance. Event will never trigger!", i); |
| | 941 | |
| | 942 | //Chance above 100, force it to be 100 |
| | 943 | if (temp.event_chance > 100) |
| 640 | | Localized_Text temp; |
| 641 | | bar.step(); |
| 642 | | |
| 643 | | Field *fields = result->Fetch(); |
| 644 | | |
| 645 | | uint32 i = fields[0].GetInt32(); |
| 646 | | |
| 647 | | temp.locale_1 = fields[1].GetString(); |
| 648 | | temp.locale_2 = fields[2].GetString(); |
| 649 | | temp.locale_3 = fields[3].GetString(); |
| 650 | | temp.locale_4 = fields[4].GetString(); |
| 651 | | temp.locale_5 = fields[5].GetString(); |
| 652 | | temp.locale_6 = fields[6].GetString(); |
| 653 | | temp.locale_7 = fields[7].GetString(); |
| 654 | | temp.locale_8 = fields[8].GetString(); |
| 655 | | |
| 656 | | EventAI_LocalizedTextMap[i] = temp; |
| 657 | | ++count; |
| 658 | | |
| 659 | | }while(result->NextRow()); |
| 660 | | |
| 661 | | delete result; |
| 662 | | |
| 663 | | outstring_log(""); |
| 664 | | outstring_log("TSCR: Loaded %u EventAI Localized Texts", count); |
| 665 | | }else outstring_log("TSCR: WARNING >> Loaded 0 EventAI Localized Texts. Database table `eventai_localized_texts` is empty"); |
| 666 | | |
| 667 | | // Drop Existing Script Localized Text Hash Map |
| 668 | | Script_LocalizedTextMap.clear(); |
| 669 | | |
| 670 | | // Gather Script Localized Texts |
| 671 | | result = TScriptDB.PQuery("SELECT `id`,`locale_1`,`locale_2`,`locale_3`,`locale_4`,`locale_5`,`locale_6`,`locale_7`,`locale_8`" |
| 672 | | "FROM `script_localized_texts`"); |
| 673 | | |
| 674 | | if(result) |
| 675 | | { |
| 676 | | outstring_log("TSCR: Loading Script Localized Texts...."); |
| 677 | | barGoLink bar(result->GetRowCount()); |
| 678 | | uint32 count = 0; |
| 679 | | |
| 680 | | do |
| | 945 | error_db_log("TSCR: Creature %u are using event %u with more than 100 percent chance. Adjusting to 100 percent.", temp.creature_id, i); |
| | 946 | temp.event_chance = 100; |
| | 947 | } |
| | 948 | |
| | 949 | //Individual event checks |
| | 950 | switch (temp.event_type) |
| 682 | | Localized_Text temp; |
| 683 | | bar.step(); |
| 684 | | |
| 685 | | Field *fields = result->Fetch(); |
| 686 | | |
| 687 | | uint32 i = fields[0].GetInt32(); |
| 688 | | |
| 689 | | temp.locale_1 = fields[1].GetString(); |
| 690 | | temp.locale_2 = fields[2].GetString(); |
| 691 | | temp.locale_3 = fields[3].GetString(); |
| 692 | | temp.locale_4 = fields[4].GetString(); |
| 693 | | temp.locale_5 = fields[5].GetString(); |
| 694 | | temp.locale_6 = fields[6].GetString(); |
| 695 | | temp.locale_7 = fields[7].GetString(); |
| 696 | | temp.locale_8 = fields[8].GetString(); |
| 697 | | |
| 698 | | Script_LocalizedTextMap[i] = temp; |
| 699 | | ++count; |
| 700 | | |
| 701 | | }while(result->NextRow()); |
| 702 | | |
| 703 | | delete result; |
| 704 | | |
| 705 | | outstring_log(""); |
| 706 | | outstring_log("TSCR: Loaded %u Script Localized Texts", count); |
| 707 | | }else outstring_log("TSCR: WARNING >> Loaded 0 Script Localized Texts. Database table `script_localized_texts` is empty"); |
| 708 | | |
| 709 | | //Drop existing EventAI Text hash map |
| 710 | | EventAI_Text_Map.clear(); |
| 711 | | |
| 712 | | //Gather EventAI Text Entries |
| 713 | | result = TScriptDB.PQuery("SELECT `id`,`text` FROM `eventai_texts`"); |
| 714 | | |
| 715 | | if (result) |
| 716 | | { |
| 717 | | outstring_log( "TSCR: Loading EventAI_Texts..."); |
| 718 | | barGoLink bar(result->GetRowCount()); |
| 719 | | uint32 Count = 0; |
| 720 | | |
| 721 | | do |
| | 952 | case EVENT_T_HP: |
| | 953 | case EVENT_T_MANA: |
| | 954 | case EVENT_T_TARGET_HP: |
| | 955 | { |
| | 956 | if (temp.event_param2 > 100) |
| | 957 | error_db_log("TSCR: Creature %u are using percentage event(%u) with param2 (MinPercent) > 100. Event will never trigger! ", temp.creature_id, i); |
| | 958 | |
| | 959 | if (temp.event_param1 <= temp.event_param2) |
| | 960 | error_db_log("TSCR: Creature %u are using percentage event(%u) with param1 <= param2 (MaxPercent <= MinPercent). Event will never trigger! ", temp.creature_id, i); |
| | 961 | |
| | 962 | if (temp.event_flags & EFLAG_REPEATABLE && !temp.event_param3 && !temp.event_param4) |
| | 963 | { |
| | 964 | error_db_log("TSCR: Creature %u has param3 and param4=0 (RepeatMin/RepeatMax) but cannot be repeatable without timers. Removing EFLAG_REPEATABLE for event %u.", temp.creature_id, i); |
| | 965 | temp.event_flags &= ~EFLAG_REPEATABLE; |
| | 966 | } |
| | 967 | } |
| | 968 | break; |
| | 969 | |
| | 970 | case EVENT_T_SPELLHIT: |
| | 971 | { |
| | 972 | if (temp.event_param1) |
| | 973 | { |
| | 974 | SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1); |
| | 975 | if (!pSpell) |
| | 976 | { |
| | 977 | error_db_log("TSCR: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i); |
| | 978 | continue; |
| | 979 | } |
| | 980 | |
| | 981 | if (temp.event_param2_s != -1 && temp.event_param2 != pSpell->SchoolMask) |
| | 982 | error_db_log("TSCR: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.event_param1, i); |
| | 983 | } |
| | 984 | |
| | 985 | //TODO: fix this system with SPELL_SCHOOL_MASK. Current complicate things, using int32(-1) instead of just 0 |
| | 986 | //SPELL_SCHOOL_MASK_NONE = 0 and does not exist, thus it can not ever trigger or be used in SpellHit() |
| | 987 | if (temp.event_param2_s != -1 && temp.event_param2_s > SPELL_SCHOOL_MASK_ALL) |
| | 988 | error_db_log("TSCR: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.event_param2, i); |
| | 989 | |
| | 990 | if (temp.event_param4 < temp.event_param3) |
| | 991 | error_db_log("TSCR: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); |
| | 992 | } |
| | 993 | break; |
| | 994 | |
| | 995 | case EVENT_T_RANGE: |
| | 996 | case EVENT_T_OOC_LOS: |
| | 997 | case EVENT_T_FRIENDLY_HP: |
| | 998 | case EVENT_T_FRIENDLY_IS_CC: |
| | 999 | case EVENT_T_FRIENDLY_MISSING_BUFF: |
| | 1000 | { |
| | 1001 | if (temp.event_param4 < temp.event_param3) |
| | 1002 | error_db_log("TSCR: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); |
| | 1003 | } |
| | 1004 | break; |
| | 1005 | |
| | 1006 | case EVENT_T_TIMER: |
| | 1007 | case EVENT_T_TIMER_OOC: |
| | 1008 | { |
| | 1009 | if (temp.event_param2 < temp.event_param1) |
| | 1010 | error_db_log("TSCR: Creature %u are using timed event(%u) with param2 < param1 (InitialMax < InitialMin). Event will never repeat.", temp.creature_id, i); |
| | 1011 | |
| | 1012 | if (temp.event_param4 < temp.event_param3) |
| | 1013 | error_db_log("TSCR: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); |
| | 1014 | } |
| | 1015 | break; |
| | 1016 | |
| | 1017 | case EVENT_T_KILL: |
| | 1018 | case EVENT_T_TARGET_CASTING: |
| | 1019 | { |
| | 1020 | if (temp.event_param2 < temp.event_param1) |
| | 1021 | error_db_log("TSCR: Creature %u are using event(%u) with param2 < param1 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); |
| | 1022 | } |
| | 1023 | break; |
| | 1024 | |
| | 1025 | case EVENT_T_AGGRO: |
| | 1026 | case EVENT_T_DEATH: |
| | 1027 | case EVENT_T_EVADE: |
| | 1028 | case EVENT_T_SPAWNED: |
| | 1029 | { |
| | 1030 | if (temp.event_flags & EFLAG_REPEATABLE) |
| | 1031 | { |
| | 1032 | error_db_log("TSCR: Creature %u has EFLAG_REPEATABLE set. Event can never be repeatable. Removing flag for event %u.", temp.creature_id, i); |
| | 1033 | temp.event_flags &= ~EFLAG_REPEATABLE; |
| | 1034 | } |
| | 1035 | } |
| | 1036 | break; |
| | 1037 | } |
| | 1038 | |
| | 1039 | for (uint32 j = 0; j < MAX_ACTIONS; j++) |
| 723 | | bar.step(); |
| 724 | | Field *fields = result->Fetch(); |
| 725 | | |
| 726 | | uint32 i = fields[0].GetInt32(); |
| 727 | | |
| 728 | | std::string text = fields[1].GetString(); |
| 729 | | |
| 730 | | if (!strlen(text.c_str())) |
| 731 | | error_db_log("TSCR: EventAI text %u is empty", i); |
| 732 | | |
| 733 | | EventAI_Text_Map[i] = text; |
| 734 | | ++Count; |
| 735 | | |
| 736 | | }while (result->NextRow()); |
| 737 | | |
| 738 | | delete result; |
| 739 | | |
| 740 | | outstring_log(""); |
| 741 | | outstring_log("TSCR: >> Loaded %u EventAI_Texts", Count); |
| 742 | | |
| 743 | | }else outstring_log("TSCR: WARNING >> Loaded 0 EventAI_Texts. DB table `EventAI_Texts` is empty."); |
| 744 | | |
| 745 | | //Gather event data |
| 746 | | result = TScriptDB.PQuery("SELECT `id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`" |
| 747 | | "FROM `eventai_summons`"); |
| 748 | | |
| 749 | | //Drop Existing EventSummon Map |
| 750 | | EventAI_Summon_Map.clear(); |
| 751 | | |
| 752 | | if (result) |
| 753 | | { |
| 754 | | outstring_log( "TSCR: Loading EventAI_Summons..."); |
| 755 | | barGoLink bar(result->GetRowCount()); |
| 756 | | uint32 Count = 0; |
| 757 | | |
| 758 | | do |
| 759 | | { |
| 760 | | bar.step(); |
| 761 | | Field *fields = result->Fetch(); |
| 762 | | |
| 763 | | EventAI_Summon temp; |
| 764 | | |
| 765 | | uint32 i = fields[0].GetUInt32(); |
| 766 | | temp.position_x = fields[1].GetFloat(); |
| 767 | | temp.position_y = fields[2].GetFloat(); |
| 768 | | temp.position_z = fields[3].GetFloat(); |
| 769 | | temp.orientation = fields[4].GetFloat(); |
| 770 | | temp.SpawnTimeSecs = fields[5].GetUInt32(); |
| 771 | | |
| 772 | | //Add to map |
| 773 | | EventAI_Summon_Map[i] = temp; |
| 774 | | ++Count; |
| 775 | | |
| 776 | | }while (result->NextRow()); |
| 777 | | |
| 778 | | delete result; |
| 779 | | outstring_log(""); |
| 780 | | outstring_log("TSCR: >> Loaded %u EventAI_Summons", Count); |
| 781 | | |
| 782 | | }else outstring_log("TSCR: WARNING >> Loaded 0 EventAI_Summons. DB table `EventAI_Summons` is empty."); |
| 783 | | |
| 784 | | //Gather event data |
| 785 | | result = TScriptDB.PQuery("SELECT `id`,`creature_id`,`event_type`,`event_inverse_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action1_type`,`action1_param1`,`action1_param2`,`action1_param3`,`action2_type`,`action2_param1`,`action2_param2`,`action2_param3`,`action3_type`,`action3_param1`,`action3_param2`,`action3_param3`" |
| 786 | | "FROM `eventai_scripts`"); |
| 787 | | |
| 788 | | //Drop Existing EventAI List |
| 789 | | EventAI_Event_List.clear(); |
| 790 | | |
| 791 | | if (result) |
| 792 | | { |
| 793 | | outstring_log( "TSCR: Loading EventAI_Scripts..."); |
| 794 | | barGoLink bar(result->GetRowCount()); |
| 795 | | uint32 Count = 0; |
| 796 | | |
| 797 | | do |
| 798 | | { |
| 799 | | bar.step(); |
| 800 | | Field *fields = result->Fetch(); |
| 801 | | |
| 802 | | EventAI_Event temp; |
| 803 | | |
| 804 | | temp.event_id = fields[0].GetUInt32(); |
| 805 | | uint32 i = temp.event_id; |
| 806 | | temp.creature_id = fields[1].GetUInt32(); |
| 807 | | temp.event_type = fields[2].GetUInt16(); |
| 808 | | temp.event_inverse_phase_mask = fields[3].GetUInt32(); |
| 809 | | temp.event_chance = fields[4].GetUInt8(); |
| 810 | | temp.event_flags = fields[5].GetUInt8(); |
| 811 | | temp.event_param1 = fields[6].GetUInt32(); |
| 812 | | temp.event_param2 = fields[7].GetUInt32(); |
| 813 | | temp.event_param3 = fields[8].GetUInt32(); |
| 814 | | temp.event_param4 = fields[9].GetUInt32(); |
| 815 | | |
| 816 | | //Report any errors in event |
| 817 | | if (temp.event_type >= EVENT_T_END) |
| 818 | | error_db_log("TSCR: Event %u has incorrect event type. Maybe DB requires updated version of SD2.", i); |
| 819 | | |
| 820 | | //No chance of this event occuring |
| 821 | | if (temp.event_chance == 0) |
| 822 | | error_db_log("TSCR: Event %u has 0 percent chance. Event will never trigger!", i); |
| 823 | | //Chance above 100, force it to be 100 |
| 824 | | if (temp.event_chance > 100) |
| | 1041 | temp.action[j].type = fields[10+(j*4)].GetUInt16(); |
| | 1042 | temp.action[j].param1 = fields[11+(j*4)].GetUInt32(); |
| | 1043 | temp.action[j].param2 = fields[12+(j*4)].GetUInt32(); |
| | 1044 | temp.action[j].param3 = fields[13+(j*4)].GetUInt32(); |
| | 1045 | |
| | 1046 | //Report any errors in actions |
| | 1047 | switch (temp.action[j].type) |
| 853 | | if (temp.event_param1) |
| 854 | | { |
| 855 | | SpellEntry const* pSpell = GetSpellStore()->LookupEntry(temp.event_param1); |
| 856 | | if (!pSpell) |
| 857 | | { |
| 858 | | error_db_log("TSCR: Creature %u has non-existant SpellID(%u) defined in event %u.", temp.creature_id, temp.event_param1, i); |
| 859 | | continue; |
| 860 | | } |
| 861 | | |
| 862 | | if (temp.event_param2_s != -1 && temp.event_param2 != pSpell->SchoolMask) |
| 863 | | error_db_log("TSCR: Creature %u has param1(spellId %u) but param2 is not -1 and not equal to spell's school mask. Event %u can never trigger.", temp.creature_id, temp.event_param1, i); |
| 864 | | } |
| 865 | | |
| 866 | | //TODO: fix this system with SPELL_SCHOOL_MASK. Current complicate things, using int32(-1) instead of just 0 |
| 867 | | //SPELL_SCHOOL_MASK_NONE = 0 and does not exist, thus it can not ever trigger or be used in SpellHit() |
| 868 | | if (temp.event_param2_s != -1 && temp.event_param2_s > SPELL_SCHOOL_MASK_ALL) |
| 869 | | error_db_log("TSCR: Creature %u is using invalid SpellSchoolMask(%u) defined in event %u.", temp.creature_id, temp.event_param2, i); |
| 870 | | |
| 871 | | if (temp.event_param4 < temp.event_param3) |
| 872 | | error_db_log("TSCR: Creature %u are using repeatable event(%u) with param4 < param3 (RepeatMax < RepeatMin). Event will never repeat.", temp.creature_id, i); |
| | 1082 | if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) |
| | 1083 | error_db_log("TSCR: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); |
| | 1084 | |
| | 1085 | if (temp.action[j].param1 >= TARGET_T_END) |
| | 1086 | error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1); |
| 918 | | }; |
| 919 | | |
| 920 | | for (uint32 j = 0; j < MAX_ACTIONS; j++) |
| 921 | | { |
| 922 | | temp.action[j].type = fields[10+(j*4)].GetUInt16(); |
| 923 | | temp.action[j].param1 = fields[11+(j*4)].GetUInt32(); |
| 924 | | temp.action[j].param2 = fields[12+(j*4)].GetUInt32(); |
| 925 | | temp.action[j].param3 = fields[13+(j*4)].GetUInt32(); |
| 926 | | |
| 927 | | //Report any errors in actions |
| 928 | | switch (temp.action[j].type) |
| 929 | | { |
| 930 | | case ACTION_T_SAY: |
| 931 | | case ACTION_T_YELL: |
| 932 | | case ACTION_T_TEXTEMOTE: |
| 933 | | if (GetEventAIText(temp.action[j].param1) == DEFAULT_TEXT) |
| 934 | | error_db_log("TSCR: Event %u Action %u refrences missing Localized_Text entry", i, j+1); |
| 935 | | break; |
| 936 | | |
| 937 | | case ACTION_T_SOUND: |
| 938 | | if (!GetSoundEntriesStore()->LookupEntry(temp.action[j].param1)) |
| 939 | | error_db_log("TSCR: Event %u Action %u uses non-existant SoundID %u.", i, j+1, temp.action[j].param1); |
| 940 | | break; |
| 941 | | |
| 942 | | case ACTION_T_RANDOM_SAY: |
| 943 | | case ACTION_T_RANDOM_YELL: |
| 944 | | case ACTION_T_RANDOM_TEXTEMOTE: |
| 945 | | if ((temp.action[j].param1 != 0xffffffff && GetEventAIText(temp.action[j].param1) == DEFAULT_TEXT) || |
| 946 | | (temp.action[j].param2 != 0xffffffff && GetEventAIText(temp.action[j].param2) == DEFAULT_TEXT) || |
| 947 | | (temp.action[j].param3 != 0xffffffff && GetEventAIText(temp.action[j].param3) == DEFAULT_TEXT)) |
| 948 | | error_db_log("TSCR: Event %u Action %u refrences missing Localized_Text entry", i, j+1); |
| 949 | | break; |
| 950 | | |
| 951 | | case ACTION_T_CAST: |
| 952 | | { |
| 953 | | if (!GetSpellStore()->LookupEntry(temp.action[j].param1)) |
| 954 | | error_db_log("TSCR: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param1); |
| 955 | | |
| 956 | | if (temp.action[j].param2 >= TARGET_T_END) |
| 957 | | error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1); |
| 958 | | } |
| 959 | | break; |
| 960 | | |
| 961 | | case ACTION_T_REMOVEAURASFROMSPELL: |
| 962 | | { |
| 963 | | if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) |
| 964 | | error_db_log("TSCR: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); |
| 965 | | |
| 966 | | if (temp.action[j].param1 >= TARGET_T_END) |
| 967 | | error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1); |
| 968 | | } |
| 969 | | break; |
| 970 | | |
| 971 | | case ACTION_T_CASTCREATUREGO: |
| 972 | | { |
| 973 | | if (!GetSpellStore()->LookupEntry(temp.action[j].param2)) |
| 974 | | error_db_log("TSCR: Event %u Action %u uses non-existant SpellID %u.", i, j+1, temp.action[j].param2); |
| 975 | | |
| 976 | | if (temp.action[j].param3 >= TARGET_T_END) |
| 977 | | error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1); |
| 978 | | } |
| 979 | | break; |
| 980 | | |
| 981 | | //2nd param target |
| 982 | | case ACTION_T_SUMMON_ID: |
| 983 | | { |
| 984 | | if (EventAI_Summon_Map.find(temp.action[j].param3) == EventAI_Summon_Map.end()) |
| 985 | | error_db_log("TSCR: Event %u Action %u summons missing EventAI_Summon %u", i, j+1, temp.action[j].param3); |
| 986 | | |
| 987 | | if (temp.action[j].param2 >= TARGET_T_END) |
| 988 | | error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1); |
| 989 | | } |
| 990 | | break; |
| 991 | | |
| 992 | | case ACTION_T_SUMMON: |
| 993 | | case ACTION_T_THREAT_SINGLE_PCT: |
| 994 | | case ACTION_T_QUEST_EVENT: |
| 995 | | case ACTION_T_SET_UNIT_FLAG: |
| 996 | | case ACTION_T_REMOVE_UNIT_FLAG: |
| 997 | | case ACTION_T_SET_INST_DATA64: |
| 998 | | if (temp.action[j].param2 >= TARGET_T_END) |
| 999 | | error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1); |
| 1000 | | break; |
| 1001 | | |
| 1002 | | //3rd param target |
| 1003 | | case ACTION_T_SET_UNIT_FIELD: |
| 1004 | | if (temp.action[j].param3 >= TARGET_T_END) |
| 1005 | | error_db_log("TSCR: Event %u Action %u uses incorrect Target type", i, j+1); |
| 1006 | | break; |
| 1007 | | |
| 1008 | | case ACTION_T_SET_PHASE: |
| 1009 | | if (temp.action[j].param1 > 31) |
| 1010 | | error_db_log("TSCR: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1); |
| 1011 | | break; |
| 1012 | | |
| 1013 | | case ACTION_T_INC_PHASE: |
| 1014 | | if (!temp.action[j].param1) |
| 1015 | | error_db_log("TSCR: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1); |
| 1016 | | break; |
| 1017 | | |
| 1018 | | case ACTION_T_KILLED_MONSTER: |
| 1019 | | if (temp.event_type != EVENT_T_DEATH) |
| 1020 | | outstring_log("TSCR WARNING: Event %u Action %u calling ACTION_T_KILLED_MONSTER outside of EVENT_T_DEATH", i, j+1); |
| 1021 | | break; |
| 1022 | | |
| 1023 | | case ACTION_T_SET_INST_DATA: |
| 1024 | | if (temp.action[j].param2 > 3) |
| 1025 | | error_db_log("TSCR: Event %u Action %u attempts to set instance data above encounter state 3. Custom case?", i, j+1); |
| 1026 | | break; |
| 1027 | | |
| 1028 | | default: |
| 1029 | | break; |
| 1030 | | } |
| 1031 | | |
| 1032 | | if (temp.action[j].type >= ACTION_T_END) |
| 1033 | | error_db_log("TSCR: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1); |
| | 1126 | |
| | 1127 | case ACTION_T_SET_PHASE: |
| | 1128 | if (temp.action[j].param1 > 31) |
| | 1129 | error_db_log("TSCR: Event %u Action %u attempts to set phase > 31. Phase mask cannot be used past phase 31.", i, j+1); |
| | 1130 | break; |
| | 1131 | |
| | 1132 | case ACTION_T_INC_PHASE: |
| | 1133 | if (!temp.action[j].param1) |
| | 1134 | error_db_log("TSCR: Event %u Action %u is incrementing phase by 0. Was this intended?", i, j+1); |
| | 1135 | break; |
| | 1136 | |
| | 1137 | case ACTION_T_KILLED_MONSTER: |
| | 1138 | if (temp.event_type != EVENT_T_DEATH) |
| | 1139 | outstring_log("SD2 WARNING: Event %u Action %u calling ACTION_T_KILLED_MONSTER outside of EVENT_T_DEATH", i, j+1); |
| | 1140 | break; |
| | 1141 | |
| | 1142 | case ACTION_T_SET_INST_DATA: |
| | 1143 | if (temp.action[j].param2 > 3) |
| | 1144 | error_db_log("TSCR: Event %u Action %u attempts to set instance data above encounter state 3. Custom case?", i, j+1); |
| | 1145 | break; |
| | 1146 | |
| | 1147 | default: |
| | 1148 | if (temp.action[j].type >= ACTION_T_END) |
| | 1149 | error_db_log("TSCR: Event %u Action %u has incorrect action type. Maybe DB requires updated version of SD2.", i, j+1); |
| | 1150 | break; |
| 1035 | | |
| 1036 | | //Add to list |
| 1037 | | EventAI_Event_List.push_back(temp); |
| 1038 | | ++Count; |
| 1039 | | |
| 1040 | | }while (result->NextRow()); |
| 1041 | | |
| 1042 | | delete result; |
| 1043 | | outstring_log(""); |
| 1044 | | outstring_log("TSCR: >> Loaded %u EventAI_Events", Count); |
| 1045 | | |
| 1046 | | }else outstring_log("TSCR: WARNING >> Loaded 0 EventAI_Scripts. DB table `EventAI_Scripts` is empty."); |
| 1047 | | |
| 1048 | | // Gather Script Text |
| 1049 | | result = TScriptDB.PQuery("SELECT `id`, `sound`, `type`, `language`, `text`" |
| 1050 | | "FROM `script_texts`;"); |
| 1051 | | |
| 1052 | | // Drop Existing Script Text Map |
| 1053 | | Script_TextMap.clear(); |
| 1054 | | |
| 1055 | | if(result) |
| 1056 | | { |
| 1057 | | outstring_log("TSCR: Loading Script Text..."); |
| 1058 | | barGoLink bar(result->GetRowCount()); |
| 1059 | | uint32 count = 0; |
| 1060 | | |
| 1061 | | do |
| 1062 | | { |
| 1063 | | bar.step(); |
| 1064 | | Field* fields = result->Fetch(); |
| 1065 | | ScriptText temp; |
| 1066 | | |
| 1067 | | uint32 i = fields[0].GetInt32(); |
| 1068 | | temp.SoundId = fields[1].GetInt32(); |
| 1069 | | temp.Type = fields[2].GetInt32(); |
| 1070 | | temp.Language = fields[3].GetInt32(); |
| 1071 | | temp.Text = fields[4].GetString(); |
| 1072 | | |
| 1073 | | if (temp.SoundId) |
| 1074 | | { |
| 1075 | | if (!GetSoundEntriesStore()->LookupEntry(temp.SoundId)) |
| 1076 | | error_db_log("TSCR: Id %u in table script_texts has soundid %u but sound does not exist.",i,temp.SoundId); |
| 1077 | | } |
| 1078 | | |
| 1079 | | if(!strlen(temp.Text.c_str())) |
| 1080 | | error_db_log("TSCR: Id %u in table script_texts has no text.", i); |
| 1081 | | |
| 1082 | | Script_TextMap[i] = temp; |
| 1083 | | ++count; |
| 1084 | | |
| 1085 | | }while(result->NextRow()); |
| 1086 | | |
| 1087 | | delete result; |
| 1088 | | |
| 1089 | | outstring_log(""); |
| 1090 | | outstring_log("TSCR: Loaded %u Script Texts", count); |
| 1091 | | |
| 1092 | | }else outstring_log("TSCR WARNING >> Loaded 0 Script Texts. Database table `script_texts` is empty."); |
| 1093 | | |
| 1094 | | //Free database thread and resources |
| 1095 | | TScriptDB.HaltDelayThread(); |
| 1096 | | |
| 1097 | | //***End DB queries*** |
| | 1152 | } |
| | 1153 | |
| | 1154 | //Add to list |
| | 1155 | EventAI_Event_List.push_back(temp); |
| | 1156 | ++Count; |
| | 1157 | } while (result->NextRow()); |
| | 1158 | |
| | 1159 | delete result; |
| | 1160 | |
| | 1161 | outstring_log(""); |
| | 1162 | outstring_log(">> Loaded %u EventAI scripts", Count); |
| | 1163 | }else |
| | 1164 | { |
| | 1165 | barGoLink bar(1); |
| | 1166 | bar.step(); |
| | 1167 | outstring_log(""); |
| | 1168 | outstring_log(">> Loaded 0 EventAI scripts. DB table `eventai_scripts` is empty."); |