#include #include #include #include #include using namespace tinyxml2; extern Player *player; // main.cpp extern World *currentWorld; // main.cpp extern Menu *currentMenu; extern Menu pauseMenu; extern Menu optionsMenu; extern std::string xmlFolder; extern void mainLoop(void); // main.cpp extern std::vector AIpreaddr; // entities.cpp extern std::vector AIpreload; // entities.cpp std::vector dopt; void destroyEverything(void); inline void segFault() { (*((int *)NULL))++; } int commonAIFunc(NPC *speaker){ XMLDocument xml; XMLElement *exml,*oxml; static unsigned int oldidx = 9999; const char *name; unsigned int idx = 0; bool stop = false; /* * Load the current world's XML file into memory for reading. */ xml.LoadFile(currentXML.c_str()); exml = xml.FirstChildElement("Dialog"); /* * Search for the correct dialog block. */ while(strcmp(exml->Attribute("name"),speaker->name)) exml = exml->NextSiblingElement(); exml = exml->FirstChildElement(); /* * Search for which text block should be used. */ do{ if(!strcmp(exml->Name(),"text")){ if(exml->UnsignedAttribute("id") == (unsigned)speaker->dialogIndex){ /* * Handle any quest tags */ if((oxml = exml->FirstChildElement("quest"))){ std::string qname; while ( oxml ) { if ( !(qname = oxml->StrAttribute("assign")).empty() ) player->qh.assign(qname,"None",(std::string)oxml->GetText()); else if( !(qname = oxml->StrAttribute("check")).empty() ){ if(player->qh.hasQuest(qname) && player->qh.finish(qname)){ goto CONT; }else{ oldidx = speaker->dialogIndex; speaker->dialogIndex = oxml->UnsignedAttribute("fail"); return commonAIFunc(speaker); } } oxml = oxml->NextSiblingElement(); } } CONT: /* * Handle any 'give' requests. */ if((oxml = exml->FirstChildElement("give"))){ while(oxml){ player->inv->addItem(oxml->Attribute("id"),oxml->UnsignedAttribute("count")); oxml = oxml->NextSiblingElement(); } } /* * Handle any 'take' requests. */ if((oxml = exml->FirstChildElement("take"))){ while(oxml){ player->inv->takeItem(oxml->Attribute("id"),oxml->UnsignedAttribute("count")); oxml = oxml->NextSiblingElement(); } } /* * Handle 'go to' thingy */ if ( (oxml = exml->FirstChildElement("gotox")) ) speaker->targetx = atoi(oxml->GetText()); /* * Handle dialog options. */ if((oxml = exml->FirstChildElement("option"))){ /* * Convert the list of options into a single colon-separated string. */ std::string optstr; while(oxml){ /* * Create a buffer big enough for the next option. */ optstr.append((std::string)":" + oxml->Attribute("text")); /* * Append the next option. */ dopt.push_back(oxml); oxml = oxml->NextSiblingElement(); } /* * Get the player's choice, then set the XMLElement to the option's block. */ ui::dialogBox(speaker->name,optstr.c_str(),false,exml->GetText()+1); ui::waitForDialog(); if(ui::dialogOptChosen) exml = dopt[ui::dialogOptChosen-1]; while(!dopt.empty()) dopt.pop_back(); }else{ /* * No options - simply print the text. */ ui::dialogBox(speaker->name,NULL,false,exml->GetText()); ui::waitForDialog(); } /* * Give another NPC dialog if requested. */ if((name = exml->Attribute("call"))){ for(auto &n : currentWorld->npc){ if(!strcmp(n->name,name)){ if(exml->QueryUnsignedAttribute("callid",&idx) == XML_NO_ERROR) n->dialogIndex = idx; n->addAIFunc(commonAIFunc,false); break; } } } /* * Handle the next dialog block if this one leads to another. */ if(exml->QueryUnsignedAttribute("nextid",&idx) == XML_NO_ERROR){ speaker->dialogIndex = idx; if(exml->QueryBoolAttribute("stop",&stop) == XML_NO_ERROR && stop){ speaker->dialogIndex = 9999; return 0; }else if(exml->QueryBoolAttribute("pause",&stop) == XML_NO_ERROR && stop){ //speaker->dialogIndex = 9999; return 1; }else return commonAIFunc(speaker); }else{ if(oldidx != 9999){ speaker->dialogIndex = oldidx; oldidx = 9999; return 1; }else{ speaker->dialogIndex = 9999; return 0; } } //return 1; } } exml = exml->NextSiblingElement(); }while(exml); return 0; } void commonPageFunc( Mob *callee ){ //static bool lock = false; /*if ( !lock ) { lock = true;*/ if ( !ui::dialogBoxExists ) { std::cout<<"begin\n"; ui::drawPage( callee->heyid ); while( ui::pageExists() ); std::cout<<"done\n"; //ui::waitForDialog(); callee->health = 0; //lock = false; } } void commonTriggerFunc(Mob *callee){ static bool lock = false; XMLDocument xml; XMLElement *exml; char *text,*pch; if(!lock){ lock = true; xml.LoadFile(currentXML.c_str()); exml = xml.FirstChildElement("Trigger"); while(strcmp(exml->Attribute("id"),callee->heyid.c_str())) exml = exml->NextSiblingElement(); player->vel.x = 0; ui::toggleBlackFast(); ui::waitForCover(); text = new char[256]; strcpy(text,exml->GetText()); pch = strtok(text,"\n"); while(pch){ ui::importantText(pch); ui::waitForDialog(); pch = strtok(NULL,"\n"); } delete[] text; ui::toggleBlackFast(); callee->health = 0; lock = false; } } void initEverything(void){ std::vector xmlFiles; XMLDocument xml; /* * Read the XML directory into an array. */ if ( getdir( std::string("./" + xmlFolder).c_str(), xmlFiles ) ) UserError("Error reading XML files!!!"); /* * Sort the files alphabetically. */ strVectorSortAlpha(&xmlFiles); /* * Load the first file found as currentWorld. */ for(unsigned int i=0;isspawn(0,100); currentWorld->bgmPlay(NULL); atexit(destroyEverything); } void destroyEverything(void){ currentWorld->save(); //delete currentWorld; //delete[] currentXML; while(!AIpreload.empty()) AIpreload.pop_back(); while(!AIpreaddr.empty()) AIpreaddr.pop_back(); }