int main(int argc, char* argv[]) { if (argc != 2) return -1; /* DWORD Patch Version DWORD FileCount FOREACH FileCount { BYTE Unknown DWORD Version DWORD CRC32 WORD StrLen BYTE[StrLen] FileName WORD StrLen BYTE[StrLen] VFSName } */ FILE* fh = fopen(argv[1], "rb"); FILE* oh = fopen("patchlist_php", "w"); dword PatchVersion; dword FileCount; fread(&PatchVersion, 4, 1, fh); fread(&FileCount, 4, 1, fh); for (int i = 0; i < FileCount; i++) { byte Unk; dword Version; dword CRC; word NameLen; char* Name; word VfsLen; char* Vfs; fread(&Unk, 1, 1, fh); fread(&Version, 4, 1, fh); fread(&CRC, 4, 1, fh); fread(&NameLen, 2, 1, fh); Name = (char*)calloc(1, NameLen + 1); fread(Name, NameLen, 1, fh); fread(&VfsLen, 2, 1, fh); Vfs = (char*)calloc(1, VfsLen + 1); fseek(fh, VfsLen, SEEK_CUR); fprintf(oh, "%s\tpatch0.%lu\t0_%lu_%lu.zip\t%lu\n", Name, PatchVersion, Version, MakeStrHash(Name), CRC); free(Name); } fclose(oh); fclose(fh); }
void CWorldServer::ReadQSD(strings path, dword index) { //LMA: mass exporter. bool lma_export=false; if(Config.massexport) lma_export=true; CRoseFile* fh = new CRoseFile(path, FM_READ | FM_BINARY); if(fh->IsOpen()) { // goto done; // Log(MSG_LOAD, "Loading %s", path); /* Commenting out this line, replacing MSG_LOAD with MSG_DEBUG -Terr0risT */ //Log(MSG_DEBUG, "Loading %s", path); fh->Seek(4, SEEK_CUR); dword BlockCount = fh->Get<dword>(); if(lma_export) { LogSp(MSG_INFO, " "); LogSp(MSG_INFO, " "); if(BlockCount==0) { //LogSp(MSG_INFO, "Exporting %s :: 0 block", path); } else if (BlockCount==1) { //LogSp(MSG_INFO, "Exporting %s :: 1 block", path); } else { //LogSp(MSG_INFO, "Exporting %s :: %i blocks", path,BlockCount); } //LogSp(MSG_INFO, "{"); } fh->Seek(fh->Get<word>(), SEEK_CUR); for(dword i = 0; i < BlockCount; i++) { dword RecordCount = fh->Get<dword>(); if(lma_export) { if(i>0) //LogSp(MSG_INFO, "\t "); if(RecordCount==0) { //LogSp(MSG_INFO, "\t Block %i / %i :: 0 Function",i+1,BlockCount); } else if (RecordCount==1) { //LogSp(MSG_INFO, "\t Block %i / %i :: 1 Function",i+1,BlockCount); } else { // LogSp(MSG_INFO, "\t Block %i / %i :: %i Functions",i+1,BlockCount,RecordCount); } //LogSp(MSG_INFO, "\t {"); } fh->Seek(fh->Get<word>(), SEEK_CUR); for(dword j = 0; j < RecordCount; j++) { CQuestTrigger* trigger = new CQuestTrigger(); trigger->id=((index*0x10000)+(i*0x100)+j); trigger->CheckNext = fh->Get<byte>(); trigger->ConditionCount = fh->Get<dword>(); trigger->ActionCount = fh->Get<dword>(); dword len = fh->Get<word>(); trigger->TriggerName = new char[len+1]; fh->Read(trigger->TriggerName, len, 1); trigger->TriggerName[len] = 0; if(lma_export) { char bactions[20]; char bconditions[20]; if(trigger->ConditionCount==0) { sprintf(bconditions,"0 condition"); } else if(trigger->ConditionCount==1) { sprintf(bconditions,"1 condition"); } else { sprintf(bconditions,"%i conditions",trigger->ConditionCount); } if(trigger->ActionCount==0) { sprintf(bactions,"0 action"); } else if(trigger->ActionCount==1) { sprintf(bactions,"1 action"); } else { sprintf(bactions,"%i actions",trigger->ActionCount); } // if(j>0) //LogSp(MSG_INFO, "\t\t "); //LogSp(MSG_INFO, "\t\t Function %i / %i (%s / %u) :: %s, %s",j+1,RecordCount,trigger->TriggerName,MakeStrHash(trigger->TriggerName),bconditions,bactions); //if(trigger->CheckNext) //LogSp(MSG_INFO, "\t\t\t <If Function %s returns False, we'll check the next Function (check_next activated)>",trigger->TriggerName); // LogSp(MSG_INFO, "\t\t {"); } if(trigger->ConditionCount > 0) { if(lma_export) { // LogSp(MSG_INFO, "\t\t\t Conditions (%i)",trigger->ConditionCount); // LogSp(MSG_INFO, "\t\t\t {"); } trigger->Conditions = new CQuestTrigger::SQuestDatum*[trigger->ConditionCount]; for(dword k = 0; k < trigger->ConditionCount; k++) { CQuestTrigger::SQuestDatum* data = new CQuestTrigger::SQuestDatum(); data->size = fh->Get<int>(); data->opcode = fh->Get<int>(); data->data = new byte[data->size - 8]; fh->Read(data->data, data->size - 8, 1); trigger->Conditions[k] = data; //LMA: Export if (lma_export) { //ExportQSDData(data->data,data->opcode,data->size,data); ExportQSDData(data->data,data->size,data->opcode); } } if(lma_export) { // LogSp(MSG_INFO, "\t\t\t }"); } } else { if(lma_export) { // LogSp(MSG_INFO, "\t\t\t 0 Condition"); } trigger->Conditions = NULL; } if(trigger->ActionCount > 0) { trigger->Actions = new CQuestTrigger::SQuestDatum*[trigger->ActionCount]; if(lma_export) { //LogSp(MSG_INFO, "\t\t\t Actions (%i)",trigger->ActionCount); //LogSp(MSG_INFO, "\t\t\t {"); } for(dword k = 0; k < trigger->ActionCount; k++) { CQuestTrigger::SQuestDatum* data = new CQuestTrigger::SQuestDatum(); data->size = fh->Get<int>(); data->opcode = fh->Get<int>() - 0x01000000; data->data = new byte[data->size - 8]; fh->Read(data->data, data->size - 8, 1); trigger->Actions[k] = data; //LMA: Export if (lma_export) { ExportQSDDataA(data->data,data->size,data->opcode); } } if(lma_export) { // LogSp(MSG_INFO, "\t\t\t }"); } } else { if(lma_export) { // LogSp(MSG_INFO, "\t\t\t 0 Action"); } trigger->Actions = NULL; } trigger->TriggerHash = MakeStrHash(trigger->TriggerName); TriggerList.push_back( trigger ); if(lma_export) { // LogSp(MSG_INFO, "\t\t "); // LogSp(MSG_INFO, "\t\t }"); } } if(lma_export) { // LogSp(MSG_INFO, "\t "); // LogSp(MSG_INFO, "\t }"); } } if(lma_export) { // LogSp(MSG_INFO, " "); // LogSp(MSG_INFO, "}"); } } else { //Log( MSG_ERROR, "QSD File: '%s'", path ); //Log( MSG_WARNING, "QSD File: '%s'", path ); Log( MSG_ERROR, "Could not open QSD File: '%s'", path ); } fh->Close(); delete fh; }
//LMA: exporting QSD Actions void CWorldServer::ExportQSDDataA(byte* dataorg,int size,int opcode) { char buffero[20]; char buffera[20]; char buffer[100]; UINT itemtype=0; UINT itemnum=0; //Update quest if(opcode==0) { STR_REWD_000 * data = (STR_REWD_000 *)dataorg; //0 remove, 1 start, 2 replace quest keep items, 3 replace quest delete items, 4 select switch(data->btOp) { case 0: { sprintf(buffer,"delete"); } break; case 1: { sprintf(buffer,"start"); } break; case 2: { sprintf(buffer,"replace (keep items)"); } break; case 3: { sprintf(buffer,"replace (delete items)"); } break; case 4: { sprintf(buffer,"select"); } break; default: { sprintf(buffer,"?%i?",data->btOp); } break; } LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: %s quest %i (%s)",opcode,buffer,data->iQuestSN,GServer->GetSTLQuestByID(data->iQuestSN)); return; } //Update quest items if(opcode==1) { STR_REWD_001 * data = (STR_REWD_001 *)dataorg; //0 remove, 1 start, 2 replace quest keep items, 3 replace quest delete items, 4 select switch(data->btOp) { case 0: { sprintf(buffer,"delete"); } break; case 1: { sprintf(buffer,"add"); } break; default: { sprintf(buffer,"?%i?",data->btOp); } break; } itemtype=gi(data->uiItemSN,0); itemnum=gi(data->uiItemSN,1); LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: current quest: %s %i items %u (%i:%i, %s %s), (partyop %u)",opcode,buffer,data->nDupCNT,data->uiItemSN,itemtype,itemnum,GServer->GetSTLItemPrefix(itemtype,itemnum),GServer->GetSTLObjNameByID(itemtype,itemnum),data->btPartyOpt); return; } //Set quest variable if(opcode==2) { STR_REWD_002 * data = (STR_REWD_002 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: set %i Quest Variables",opcode,data->iDataCnt); for(dword i = 0; i < data->iDataCnt; i++) { dword address = i * sizeof(STR_QUEST_DATA); address += (dword)dataorg; address += 4; STR_QUEST_DATA* curQst = (STR_QUEST_DATA*)address; LogSp(MSG_INFO,"\t\t\t\t\t\t |-> Set Quest Var[0x%04x (%u)][%i] %s %i",curQst->m_wVarTYPE,curQst->m_wVarTYPE,curQst->m_wVarNO,Operators(curQst->btOp,buffero),curQst->nValue); } return; } //Udapte Stats if(opcode==3) { STR_REWD_003 * data = (STR_REWD_003 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Update %i Stats",opcode,data->iDataCnt); for(dword i = 0; i < data->iDataCnt; i++) { dword address = i * 0x0C; address += (dword)dataorg; address += 4; STR_ABIL_DATA* curAbil = (STR_ABIL_DATA*)address; LogSp(MSG_INFO,"\t\t\t\t\t\t |-> Set Stat %s %s %i",Abilities(curAbil->iType,buffera),Operators(curAbil->btOp,buffero),curAbil->iValue); } return; } //Set quest variable if(opcode==4) { STR_REWD_004 * data = (STR_REWD_004 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: set %i Quest Variables",opcode,data->iDataCnt); for(dword i = 0; i < data->iDataCnt; i++) { dword address = i * sizeof(STR_QUEST_DATA); address += (dword)dataorg; address += 4; STR_QUEST_DATA* curQst = (STR_QUEST_DATA*)address; LogSp(MSG_INFO,"\t\t\t\t\t\t |-> Set Quest Var[0x%04x (%u)][%i] %s %i",curQst->m_wVarTYPE,curQst->m_wVarTYPE,curQst->m_wVarNO,Operators(curQst->btOp,buffero),curQst->nValue); } return; } //Give reward if(opcode==5) { STR_REWD_005 * data = (STR_REWD_005 *)dataorg; switch(data->btTarget) { case 0://EXP { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Give %u Exp, (partyop %u, itemopt %u, nPartyOpt %u)",opcode,data->iValue,data->btPartyOpt,data->nItemOpt,data->nPartyOpt); } break; case 1://Zuly { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Give %u Zuly, (partyop %u, itemopt %u, nPartyOpt %u)",opcode,data->iValue,data->btPartyOpt,data->nItemOpt,data->nPartyOpt); } break; case 2://Item { CItem nItem; itemtype=gi(data->iItemSN,0); itemnum=gi(data->iItemSN,1); nItem.itemtype = itemtype; nItem.itemnum = itemnum; if(nItem.IsStackable()) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Give %i (+formula()) item %u (%i:%i, %s %s), (partyop %u, itemopt %u, nPartyOpt %u)",opcode,data->iValue,data->iItemSN,nItem.itemtype,nItem.itemnum,GServer->GetSTLItemPrefix(itemtype,itemnum),GServer->GetSTLObjNameByID(nItem.itemtype,nItem.itemnum),data->btPartyOpt,data->nItemOpt,data->nPartyOpt); } else { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Give 1 item %u (%i:%i, %s %s), (partyop %u, itemopt %u, nPartyOpt %u)",opcode,data->iItemSN,nItem.itemtype,nItem.itemnum,GServer->GetSTLItemPrefix(itemtype,itemnum),GServer->GetSTLObjNameByID(nItem.itemtype,nItem.itemnum),data->btPartyOpt,data->nItemOpt,data->nPartyOpt); } } break; default: { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Give Unknown reward %i, item %u, count / value %u, (partyop %u, itemopt %u, nPartyOpt %u)",opcode,data->btTarget,data->iItemSN,data->iValue,data->btPartyOpt,data->nItemOpt,data->nPartyOpt); } break; } return; } //restore HP / MP if(opcode==6) { STR_REWD_006 * data = (STR_REWD_006 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Restore %i%% HP, %i%% MP (partyop %u)",opcode,data->iPercentOfHP, data->iPercentOfMP,data->btPartyOpt); return; } //teleport if(opcode==7) { STR_REWD_007 * data = (STR_REWD_007 *)dataorg; if(data->btPartyOpt!=0) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Teleport to map %i (%s) at (%.2f,%.2f), with party members. (partyop %u)",opcode,data->iZoneSN,GServer->GetSTLZoneNameByID(data->iZoneSN),(float)(data->iX/100),(float)(data->iY/100),data->btPartyOpt); } else { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Teleport to map %i (%s) at (%.2f,%.2f), (partyop %u)",opcode,data->iZoneSN,GServer->GetSTLZoneNameByID(data->iZoneSN),(float)(data->iX/100),(float)(data->iY/100),data->btPartyOpt); } return; } //Spawn monster if(opcode==8) { STR_REWD_008 * data = (STR_REWD_008 *)dataorg; if(data->iX==0||data->iY==0||data->iZoneSN==0) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn %i monsters %i (%s) near me (team %i), (btwho)",opcode,data->iHowMany,data->iMonsterSN,GServer->GetSTLMonsterNameByID(data->iMonsterSN),data->iTeamNo,data->btWho); } else { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn %i monsters %i (%s) to map %i (%s) at (%.2f,%.2f) (team %i), (btwho %u)",opcode,data->iHowMany,data->iMonsterSN,GServer->GetSTLMonsterNameByID(data->iMonsterSN),data->iZoneSN,GServer->GetSTLZoneNameByID(data->iZoneSN),(float)(data->iX/100),(float)(data->iY/100),data->iTeamNo,data->btWho); } return; } //Execute Quest Trigger if(opcode==9) { STR_REWD_009 * data = (STR_REWD_009 *)dataorg; char* tempName = reinterpret_cast<char*>(&data->szNextTriggerSN) - 2; dword hash = MakeStrHash(tempName); LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Execute Quest Trigger %s (%u)",opcode,tempName,hash); return; } //Reset Stats. if(opcode==10) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Reset Stats to default values",opcode); return; } //Update Object Var.. if(opcode==11) { STR_REWD_011 * data = (STR_REWD_011 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Update variable",opcode); if(data->btWho==0) { LogSp(MSG_INFO,"\t\t\t\t\t\t |-> Update ObjVar[%i] %s %i, who=%i (NPC)",data->nVarNo,Operators(data->btOp,buffero),data->iValue,data->btWho); } else if (data->btWho==1) { LogSp(MSG_INFO,"\t\t\t\t\t\t |-> Update ObjVar[%i] %s %i, who=%i (Event Object)",data->nVarNo,Operators(data->btOp,buffero),data->iValue,data->btWho); } else { LogSp(MSG_INFO,"\t\t\t\t\t\t |-> Update ObjVar[%i] %s %i, who=?(%i)?",data->nVarNo,Operators(data->btOp,buffero),data->iValue,data->btWho); } return; } //NPC Speak... if(opcode==12) { //Log(MSG_INFO, "NPC trying to speak"); STR_REWD_012 * data = (STR_REWD_012 *)dataorg; //Log(MSG_INFO,"\t\t\t\t\t ACT %.3i: NPC Speak (NOT CODED for Client) (CODED for Monsters / NPC)",opcode); if(data->btMsgType == 1) { //Log(MSG_INFO,"\t\t\t\t\t\t |-> NPC Shouts LTB string %i, %s",data->iStrID,GServer->LtbstringQSD[data->iStrID]->LTBstring); } else if(data->btMsgType == 2) { //Log(MSG_INFO,"\t\t\t\t\t\t |-> NPC Announces LTB string %i, %s",data->iStrID,GServer->LtbstringQSD[data->iStrID]->LTBstring); } else { //Log(MSG_INFO,"\t\t\t\t\t\t |-> NPC ?(%i)? LTB string %i, %s",data->btMsgType,data->iStrID,GServer->LtbstringQSD[data->iStrID]->LTBstring); } return; } //Unknown (execute quest trigger?) if(opcode==13) { STR_REWD_013 * data = (STR_REWD_013 *)dataorg; char* tempName = reinterpret_cast<char*>(&data->szTriggerName) - 2; dword hash = MakeStrHash(tempName); LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Execute Quest Trigger %s (%u) (who %u, isec %u, nexttrigger %u)",opcode,tempName,hash,data->btWho,data->iSec,data->m_HashNextTrigger); return; } //Learn Skill if(opcode==14) { STR_REWD_014 * data = (STR_REWD_014 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Learn Skill %i (%s), (op %u)",opcode,data->iSkillNo,GServer->GetSTLSkillByID(data->iSkillNo),data->btOp); return; } //Set Quest Flag if(opcode==15) { STR_REWD_015 * data = (STR_REWD_015 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set Quest Flag[%u]=%i",opcode,data->nSN,data->btOp); return; } //Unknown... if(opcode==16) { STR_REWD_016 * data = (STR_REWD_016 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown (NOT CODED), (op %u)",opcode,data->nGroupSN); return; } //reset all quest flags... if(opcode==17) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Reset All Quest Flags",opcode); return; } //Send Announcment... if(opcode==18) { STR_REWD_018 * data = (STR_REWD_018 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Send Announcment (NOT CODED), (strid %u, ncnt %u)",opcode,data->iStrID,data->nCnt); return; } //Execute Quest Trigger in Other Map... if(opcode==19) { STR_REWD_019 * data = (STR_REWD_019 *)dataorg; char* tempName = reinterpret_cast<char*>(&data->TriggerName) - 2; dword hash = MakeStrHash(tempName); LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Execute Quest %s (hash %u) in Other Map %i (%s) for team %i (NOT CODED for Client) (CODED for Monsters / NPC), (triggerlength %u)",opcode,tempName,hash,data->nZoneNo,GServer->GetSTLZoneNameByID(data->nZoneNo),data->nTeamNo,data->nTriggerLength); return; } //PvP Status... if(opcode==20) { STR_REWD_020 * data = (STR_REWD_020 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: PvP Status set to %i (for maps mainly) (CODED FOR PLAYERS)",opcode,data->btNoType); return; } //Set Respawn Position... if(opcode==21) { STR_REWD_021 * data = (STR_REWD_021 *)dataorg; float X=(float)(data->iX)/((float)100); float Y=(float)(data->iY)/((float)100); LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set Respawn Position to current map [%.2f;%.2f].",opcode,X,Y); return; } //Unknown... if(opcode==22) { STR_REWD_022 * data = (STR_REWD_022 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown (NOT CODED), (op %u)",opcode,data->btOp); return; } //Raise Clan Grade if(opcode==23) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Raise clan grade (+1) (NOT FULLY CODED) ",opcode); return; } //Clan Money... if(opcode==24) { STR_REWD_024 * data = (STR_REWD_024 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Clan Money btop=%i, money %i (NOT CODED)",opcode,data->btOP,data->iMONEY); return; } //Clan Points... if(opcode==25) { STR_REWD_025 * data = (STR_REWD_025 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Clan Points %s %i",opcode,Operators(data->btOP,buffero),data->nPOINT); return; } //Clan Skill... if(opcode==26) { STR_REWD_026 * data = (STR_REWD_026 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Clan Skill (NOT CODED), (skill %u,op %u)",opcode,data->nSkillNo,data->btOP); return; } //Clan Contribution... if(opcode==27) { STR_REWD_027 * data = (STR_REWD_027 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Clan Contribution (NOT CODED), (cont %u,op %u)",opcode,data->nCONT,data->btOP); return; } //Clan teleport if(opcode==28) { STR_REWD_028 * data = (STR_REWD_028 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Teleport all me and my clan members to map %i at (%.2f,%.2f) random range %i ",opcode,data->nZoneNo,(float)(data->iX/100),(float)(data->iY/100),data->iRange); return; } //LMA: Lua? if(opcode==29) { STR_REWD_029 * data = (STR_REWD_029 *)dataorg; char* tempName = reinterpret_cast<char*>(&data->luaName)-2; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: execute Lua %s (luaLen=%u) (NOT CODED, CLIENT SIDE ONLY?)",opcode,tempName,data->luaLen); return; } //Unspawn a NPC if(opcode==34) { STR_REWD_034 * data = (STR_REWD_034 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Removing previously selected NPC. (op %u)",opcode,data->btOP); return; } //Really unknown :) LogSp(MSG_WARNING,"\t\t\t\t\t ACT %.3i: Impossible to export QSD opcode, size %u",opcode,size-8); return; }
//LMA: We export AIP Actions here void CWorldServer::ExportAipDataA(byte* dataorg,int size,int opcode) { UINT itemtype=0; UINT itemnum=0; //Unknown if(opcode==0) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown",opcode); return; } //Action if(opcode==1) { STR_AI_ACT_001 * data = (STR_AI_ACT_001 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Action, (0x781) %i",opcode,data->cAction); return; } //Say LTB string. if(opcode==2) { STR_AI_ACT_002 * data = (STR_AI_ACT_002 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Say LTB String %i (%s) (NOT CODED but OK since client Side)",opcode,data->iStrID,GServer->Ltbstring[data->iStrID]->LTBstring); return; } //Move if(opcode==3) { STR_AI_ACT_003 * data = (STR_AI_ACT_003 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Move from current position, distance %i at stance %i",opcode,data->iDistance,data->cSpeed); return; } //Move 2 if(opcode==4) { STR_AI_ACT_004 * data = (STR_AI_ACT_004 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Move from spawn position, distance %i at stance %i",opcode,data->iDistance,data->cSpeed); return; } //Move 3 if(opcode==5) { STR_AI_ACT_005 * data = (STR_AI_ACT_005 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Move from a char's position, distance 2 at stance %i",opcode,data->cSpeed); return; } //attack a player if ok with some stuff... if(opcode==6) { STR_AI_ACT_006 * data = (STR_AI_ACT_006 *)dataorg; char buffer[20]; char buffer1[20]; if(data->cMoreLess == 0) { sprintf(buffer,"biggest"); } else { sprintf(buffer,"lowest"); } switch(data->cAbType) { case 0: //level sprintf(buffer1,"level"); break; case 1: //Attack power sprintf(buffer1,"attack power"); break; case 2: //defense sprintf(buffer1,"defense"); break; case 3: //Magic Def sprintf(buffer1,"MDEF"); break; case 4: // HP sprintf(buffer1,"HP"); break; case 5: // Charm sprintf(buffer1,"charm"); break; } LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Attacks a player within distance %i if player has %s %s",opcode,data->iDistance,buffer, buffer1); return; } //Unknown if(opcode==7) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown",opcode); return; } //Move 4 if(opcode==8) { STR_AI_ACT_008 * data = (STR_AI_ACT_008 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Monster moves to %i %% between source and current position at stance %i ",opcode,data->iDistance,data->cSpeed); return; } //Convert to another monster. if(opcode==9) { STR_AI_ACT_009 * data = (STR_AI_ACT_009 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Converts to monster %i (%s)",opcode,data->wMonster,GServer->GetSTLMonsterNameByID(data->wMonster)); return; } //Spawn monsters. if(opcode==10) { STR_AI_ACT_010 * data = (STR_AI_ACT_010 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn 1 monster %i near me",opcode,data->wMonster,GServer->GetSTLMonsterNameByID(data->wMonster)); return; } //Call for backup.. if(opcode==11) { STR_AI_ACT_011 * data = (STR_AI_ACT_011 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Call for backup, range %i max %i monsters",opcode,data->iDistance,data->iNumOfMonster); return; } //Attack. if(opcode==12) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Attacks NearChar",opcode); return; } //Attack. if(opcode==13) { STR_AI_ACT_013 * data = (STR_AI_ACT_013 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Attacks FindChar",opcode); return; } //Unknown if(opcode==14) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown",opcode); return; } //retaliates. if(opcode==15) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Retaliates against the last player who hit me",opcode); return; } //run away. if(opcode==16) { STR_AI_ACT_016 * data = (STR_AI_ACT_016 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Runs away, distance %i",opcode,data->iDistance); return; } //drop item. if(opcode==17) { STR_AI_ACT_017 * data17 = (STR_AI_ACT_017 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Drops 1 item amongst:",opcode); for(int k=0;k<6;k++) { int nItem = data17->items[k]; if (nItem==0) continue; if(k==5&&nItem==0xCDCD) continue; itemtype=gi(nItem,0); itemnum=gi(nItem,1); LogSp(MSG_INFO,"\t\t\t\t\t\t |-> Item %u : (%i:%i), %s %s",nItem,itemtype,itemnum,GServer->GetSTLItemPrefix(itemtype,itemnum),GServer->GetSTLObjNameByID(itemtype,itemnum)); } return; } //Unknown if(opcode==18) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown",opcode); return; } //Attack (same as 12) if(opcode==19) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Attacks NearChar",opcode); return; } //Spawn monster if(opcode==20) { STR_AI_ACT_020 * data = (STR_AI_ACT_020 *)dataorg; if(data->btPos == 0) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn monster %i (%s) distance %i ",opcode,data->cMonster,GServer->GetSTLMonsterNameByID(data->cMonster),data->iDistance); } else if(data->btPos == 1) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn monster %i (%s) distance %i ",opcode,data->cMonster,GServer->GetSTLMonsterNameByID(data->cMonster),data->iDistance); } else if(data->btPos == 2) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn monster %i (%s) distance %i near target",opcode,data->cMonster,GServer->GetSTLMonsterNameByID(data->cMonster),data->iDistance); } else { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn monster %i (%s) distance %i near ??? (%i)",opcode,data->cMonster,GServer->GetSTLMonsterNameByID(data->cMonster),data->iDistance,data->btPos); } return; } //Unknown if(opcode==21) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown",opcode); return; } //Unknown if(opcode==22) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Unknown",opcode); return; } //ghostseeds and ghosts and player summons commit suicide if(opcode==23) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Time to suicide",opcode); return; } //Do Skill if(opcode==24) { STR_AI_ACT_024 * data = (STR_AI_ACT_024 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Monster does skill %i (%s) ",opcode,data->nSkill,GServer->GetSTLSkillByID(data->nSkill)); return; } //Set Variable. if(opcode==25) { STR_AI_ACT_025 * data = (STR_AI_ACT_025 *)dataorg; char buffer[3]; switch(data->btOp) { case 5: sprintf(buffer,"="); break; case 6: sprintf(buffer,"+="); break; case 7: sprintf(buffer,"-="); break; case 9: sprintf(buffer,"++"); break; default: sprintf(buffer,"??"); break; } if(data->btVarIDX==0) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set ObjVar[%i] (eventID) %s %i ",opcode,data->btVarIDX,buffer,data->iValue); } else { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set ObjVar[%i] %s %i ",opcode,data->btVarIDX,buffer,data->iValue); } return; } //set variable 2 (world?) if(opcode==26) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set variable (world?) (NOT CODED)",opcode); return; } //set variable 2 (economy?) if(opcode==27) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set variable (economy?) (NOT CODED)",opcode); return; } //shouts / announces LTB String. if(opcode==28) { STR_AI_ACT_028 * data = (STR_AI_ACT_028 *)dataorg; switch(data->btMsgType) { case 0: //whisper to client LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Whisper LTB string %i: %s",opcode,data->iStrID,GServer->Ltbstring[data->iStrID]->LTBstring); break; case 1: //shout to map { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Shouts LTB string %i: %s",opcode,data->iStrID,GServer->Ltbstring[data->iStrID]->LTBstring); } break; case 2: //announce to server. { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Announces LTB string %i: %s",opcode,data->iStrID,GServer->Ltbstring[data->iStrID]->LTBstring); } break; default: { //? LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Tells(%i)? LTB string %i: %s (NOT CODED)",opcode,data->btMsgType,data->iStrID,GServer->Ltbstring[data->iStrID]->LTBstring); } break; } return; } //moves to my owner location.. if(opcode==29) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Moves to owner's location",opcode); return; } //Do Quest Trigger. if(opcode==30) { STR_AI_ACT_030 * data = (STR_AI_ACT_030 *)dataorg; char* tempName = reinterpret_cast<char*>(&data->szTrigger) - 2; dword hash = MakeStrHash(tempName); LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Do quest trigger %s, %u",opcode,tempName,hash); return; } //monster attacks owner's target.. if(opcode==31) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Monster attacks owner's target",opcode); return; } //Set Zone ? if(opcode==32) { STR_AI_ACT_032 * data = (STR_AI_ACT_032 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set Pvp to %i in Zone %i",opcode,data->btOnOff,data->nZoneNo); return; } //Set Zone ? if(opcode==33) { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set Zone ? (NOT CODED)",opcode); return; } //Gives Item to caller. if(opcode==34) { STR_AI_ACT_034 * data = (STR_AI_ACT_034 *)dataorg; char itemtypes[15] = {4,0,0,0,0,0,0,0,0,0,1,2,2,4,3}; //LMA: exact way. itemtype = GServer->gi(data->nItemNum,0); itemnum = GServer->gi(data->nItemNum,1); int count = data->nCount; int durability=100; if( itemtypes[itemtype] == 0 ) { durability = GServer->STB_ITEM[itemtype-1].rows[itemnum][29]; } if (durability==0) { durability=100; } LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Gives %i item %i::%i (%s %s), durability %i to master",opcode,count,itemtype,itemnum,GServer->GetSTLItemPrefix(itemtype,itemnum),GServer->GetSTLObjNameByID(itemtype,itemnum),durability); return; } //Set Variable. if(opcode==35) { STR_AI_ACT_035 * data = (STR_AI_ACT_035 *)dataorg; char buffer[3]; switch(data->btOp) { case 5: sprintf(buffer,"="); break; case 6: sprintf(buffer,"+="); break; case 7: sprintf(buffer,"-="); break; case 9: sprintf(buffer,"++"); break; default: sprintf(buffer,"?(%i)?",data->btOp); break; } LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Set monster var[%i] %s %i ",opcode,data->nVarIDX,buffer,data->iValue); return; } //spawn monster with a master? if(opcode==36) { STR_AI_ACT_036 * data = (STR_AI_ACT_036 *)dataorg; LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: Spawn monster %i (%s) with master %i near me",opcode,data->nMonster,GServer->GetSTLMonsterNameByID(data->nMonster),data->btMaster); return; } //spawn monster with btmaster? if(opcode==37) { STR_AI_ACT_037 * data = (STR_AI_ACT_037 *)dataorg; if(data->nPos == 0) //spawn monster in a circle with radius iDistance around my current position { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: spawn monster %i (%s) with master %i near me",opcode,data->nMonster,GServer->GetSTLMonsterNameByID(data->nMonster),data->btMaster); } else if(data->nPos == 1) //spawn monster in a circle with radius iDistance around my destiny position { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: spawn monster %i (%s) with master %i near master",opcode,data->nMonster,GServer->GetSTLMonsterNameByID(data->nMonster),data->btMaster); } else if(data->nPos == 2) //spawn monster in a circle with radius iDistance around my target's current position { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: spawn monster %i (%s) with master %i near target",opcode,data->nMonster,GServer->GetSTLMonsterNameByID(data->nMonster),data->btMaster); } else { LogSp(MSG_INFO,"\t\t\t\t\t ACT %.3i: spawn monster %i (%s) with master %i near ?(%i)?",opcode,data->nMonster,GServer->GetSTLMonsterNameByID(data->nMonster),data->btMaster,data->nPos); } return; } //Really unknown :) LogSp(MSG_WARNING,"\t\t\t\t\t ACT %.3i: Impossible to export AIP opcode, size %i",opcode,size-8); return; }
void CWorldServer::ReadQSD(strings path, dword index){ string tmp("3DData/QUESTDATA/"); while (*++path != '\\'); while (*++path != '\\'); while (*path != 0) tmp.push_back(tolower(*++path)); /* Log(MSG_INFO, "Openning : %s", tmp.c_str()); */ CRoseFile* fh = new CRoseFile(tmp.c_str(), FM_READ | FM_BINARY); if(fh->IsOpen()) { // goto done; Log(MSG_LOAD, "Loading %s ", tmp.c_str()); fh->Seek(4, SEEK_CUR); dword BlockCount = fh->Get<dword>(); fh->Seek(fh->Get<word>(), SEEK_CUR); for(dword i = 0; i < BlockCount; i++){ dword RecordCount = fh->Get<dword>(); fh->Seek(fh->Get<word>(), SEEK_CUR); for(dword j = 0; j < RecordCount; j++){ CQuestTrigger* trigger = new CQuestTrigger(); trigger->id=((index*0x10000)+(i*0x100)+j); trigger->CheckNext = fh->Get<byte>(); trigger->ConditionCount = fh->Get<dword>(); trigger->ActionCount = fh->Get<dword>(); dword len = fh->Get<word>(); trigger->TriggerName = new char[len+1]; fh->Read(trigger->TriggerName, len, 1); trigger->TriggerName[len] = 0; if(trigger->ConditionCount > 0){ trigger->Conditions = new CQuestTrigger::SQuestDatum*[trigger->ConditionCount]; for(dword k = 0; k < trigger->ConditionCount; k++){ CQuestTrigger::SQuestDatum* data = new CQuestTrigger::SQuestDatum(); data->size = fh->Get<int>(); data->opcode = fh->Get<int>(); data->data = new byte[data->size - 8]; fh->Read(data->data, data->size - 8, 1); trigger->Conditions[k] = data; } }else{ trigger->Conditions = NULL; } if(trigger->ActionCount > 0){ trigger->Actions = new CQuestTrigger::SQuestDatum*[trigger->ActionCount]; for(dword k = 0; k < trigger->ActionCount; k++){ CQuestTrigger::SQuestDatum* data = new CQuestTrigger::SQuestDatum(); data->size = fh->Get<int>(); data->opcode = fh->Get<int>() - 0x01000000; data->data = new byte[data->size - 8]; fh->Read(data->data, data->size - 8, 1); trigger->Actions[k] = data; } }else{ trigger->Actions = NULL; } trigger->TriggerHash = MakeStrHash(trigger->TriggerName); TriggerList.push_back( trigger ); } } }else Log( MSG_ERROR, "QSD File: '%s'", tmp.c_str() ); fh->Close(); delete fh; }