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."); |