TNPC::TNPC(const CString& pImage, const CString& pScript, float pX, float pY, TLevel* pLevel, bool pLevelNPC, bool trimCode) : levelNPC(pLevelNPC), x(pX), y(pY), hurtX(32.0f), hurtY(32.0f), x2((int)(pX*16)), y2((int)(pY*16)), gmaplevelx(0), gmaplevely(0), id(0), rupees(0), darts(0), bombs(0), glovePower(0), bombPower(0), swordPower(0), shieldPower(0), visFlags(1), blockFlags(0), sprite(2), power(0), ap(50), image(pImage), gani("idle"), level(pLevel) { memset((void*)colors, 0, sizeof(colors)); memset((void*)saves, 0, sizeof(saves)); memset((void*)modTime, 0, sizeof(modTime)); // imagePart needs to be Graal-packed. for (int i = 0; i < 6; i++) imagePart.writeGChar(0); // Set the gmap levels. TMap* gmap = level->getMap(); if (gmap && gmap->getType() == MAPTYPE_GMAP) { gmaplevelx = (unsigned char)gmap->getLevelX(level->getLevelName()); gmaplevely = (unsigned char)gmap->getLevelY(level->getLevelName()); } // We need to alter the modTime of the following props as they should be always sent. // If we don't, they won't be sent until the prop gets modified. modTime[NPCPROP_IMAGE] = modTime[NPCPROP_SCRIPT] = modTime[NPCPROP_X] = modTime[NPCPROP_Y] = modTime[NPCPROP_VISFLAGS] = modTime[NPCPROP_ID] = modTime[NPCPROP_SPRITE] = modTime[NPCPROP_GMAPLEVELX] = modTime[NPCPROP_GMAPLEVELY] = modTime[NPCPROP_X2] = modTime[NPCPROP_Y2] = time(0); // Search if the NPC is a sparringzone NPC. if (pScript.subString(0, 12) == "sparringzone") pLevel->setSparringZone(true); // Remove comments and separate clientside and serverside scripts. std::vector<CString> parsedCode = TNPC::removeComments(pScript, trimCode); if (parsedCode.size() == 1) clientScript = CString("//#CLIENTSIDE\xa7") << parsedCode[0]; else if (parsedCode.size() > 1) { serverScript = parsedCode[0]; clientScript = "//#CLIENTSIDE\xa7"; for (unsigned int i = 1; i < parsedCode.size(); ++i) clientScript << parsedCode[i]; } // Search for toweapons in the clientside code and extract the name of the weapon. weaponName = toWeaponName(clientScript); // Just a little warning for people who don't know. if (clientScript.length() > 0x3FFF) printf("WARNING: Clientside script of NPC (%s) exceeds the limit of 16383 bytes.\n", (weaponName.length() != 0 ? weaponName.text() : image.text())); // TODO: Create plugin hook so NPCServer can acquire/format code. }
TNPC::TNPC(const CString& pImage, const CString& pScript, float pX, float pY, TServer* pServer, TLevel* pLevel, bool pLevelNPC, bool trimCode) : levelNPC(pLevelNPC), x(pX), y(pY), hurtX(32.0f), hurtY(32.0f), x2((int)(pX*16)), y2((int)(pY*16)), gmaplevelx(0), gmaplevely(0), id(0), rupees(0), darts(0), bombs(0), glovePower(0), bombPower(0), swordPower(0), shieldPower(0), visFlags(1), blockFlags(0), sprite(2), power(0), ap(50), image(pImage), gani("idle"), level(pLevel), server(pServer) { memset((void*)colors, 0, sizeof(colors)); memset((void*)saves, 0, sizeof(saves)); memset((void*)modTime, 0, sizeof(modTime)); // bowImage for pre-2.x clients. bowImage >> (char)0; // imagePart needs to be Graal-packed. for (int i = 0; i < 6; i++) imagePart.writeGChar(0); // Set the gmap levels. TMap* gmap = level->getMap(); if (gmap && gmap->getType() == MAPTYPE_GMAP) { gmaplevelx = (unsigned char)gmap->getLevelX(level->getLevelName()); gmaplevely = (unsigned char)gmap->getLevelY(level->getLevelName()); } // We need to alter the modTime of the following props as they should be always sent. // If we don't, they won't be sent until the prop gets modified. modTime[NPCPROP_IMAGE] = modTime[NPCPROP_SCRIPT] = modTime[NPCPROP_X] = modTime[NPCPROP_Y] = modTime[NPCPROP_VISFLAGS] = modTime[NPCPROP_ID] = modTime[NPCPROP_SPRITE] = modTime[NPCPROP_GMAPLEVELX] = modTime[NPCPROP_GMAPLEVELY] = modTime[NPCPROP_X2] = modTime[NPCPROP_Y2] = time(0); // See if the NPC sets the level as a sparring zone. if (pScript.subString(0, 12) == "sparringzone") pLevel->setSparringZone(true); // See if the NPC sets the level as singleplayer. if (pScript.subString(0, 12) == "singleplayer") pLevel->setSingleplayer(true); // Remove comments and separate clientside and serverside scripts. CString nocomments = removeComments(pScript, "\xa7"); if (server->hasNPCServer() && nocomments.find("//#CLIENTSIDE") != -1) { serverScript = nocomments.readString("//#CLIENTSIDE"); clientScript = CString("//#CLIENTSIDE\xa7") << nocomments.readString(""); } else clientScript = nocomments; // Trim the code if specified. if (trimCode) { if (!serverScript.isEmpty()) { std::vector<CString> code = serverScript.tokenize("\xa7"); serverScript.clear(); for (std::vector<CString>::iterator i = code.begin(); i != code.end(); ++i) serverScript << (*i).trim() << "\xa7"; } if (!clientScript.isEmpty()) { std::vector<CString> code = clientScript.tokenize("\xa7"); clientScript.clear(); for (std::vector<CString>::iterator i = code.begin(); i != code.end(); ++i) clientScript << (*i).trim() << "\xa7"; } } // Do joins. if (!serverScript.isEmpty()) serverScript = doJoins(serverScript, server->getFileSystem()); if (!clientScript.isEmpty()) clientScript = doJoins(clientScript, server->getFileSystem()); // Search for toweapons in the clientside code and extract the name of the weapon. weaponName = toWeaponName(clientScript); // Just a little warning for people who don't know. if (clientScript.length() > 0x2FDF) printf("WARNING: Clientside script of NPC (%s) exceeds the limit of 12255 bytes.\n", (weaponName.length() != 0 ? weaponName.text() : image.text())); // TODO: Create plugin hook so NPCServer can acquire/format code. }