Example #1
0
bool SL_Broadcast(Server* srv, Packet& pack)
{
    uint8_t packet_id;
    pack >> packet_id;

    if(packet_id != 0x13) return false;
    std::string message;
    pack >> message;

    Printf(LOG_Info, "[SL] %s\n", message.c_str());

    Packet msgP;
    msgP << (uint8_t)0x63;
    msgP << message;

    for(std::vector<Server*>::iterator it = Servers.begin(); it != Servers.end(); ++it)
    {
        Server* srv = (*it);
        if(srv && srv->Layer)
        {
            if(SOCK_SendPacket(srv->Layer->Socket, msgP, 20) != 0)
                srv->Layer->Flags.Connected = false;
        }
    }

    return true;
}
Example #2
0
bool SLCMD_MutePlayer(Server* srv, std::string login, uint32_t unmutedate)
{
    Packet msgP;
    msgP << (uint8_t)0x65;
    msgP << login;
    msgP << unmutedate;
    return (SOCK_SendPacket(srv->Layer->Socket, msgP, 20) == 0);
}
Example #3
0
bool SVCMD_ReceivedCharacter(ServerConnection* conn, std::string login)
{
    Packet pck;
    pck << (uint8_t)0xD3;
    pck << (uint32_t)0;
    pck << login;

    return (SOCK_SendPacket(conn->Socket, pck, conn->Version) == 0);
}
Example #4
0
bool SLCMD_Screenshot(Server* srv, std::string login, uint32_t uid, bool done, std::string url)
{
    Packet msgP;
    msgP << (uint8_t)0x64;
    msgP << login;
    msgP << uid;
    msgP << done;
    msgP << url;
    return (SOCK_SendPacket(srv->Layer->Socket, msgP, 20) == 0);
}
Example #5
0
unsigned long SV_TryClient(ServerConnection* conn, unsigned long id1, unsigned long id2, std::string login, std::string nickname, unsigned char sex)
{
    char* data = NULL;
    unsigned long size = 0;

    std::string nickname1 = nickname;
    std::string nickname2;

    if(!Login_GetCharacter(login, id1, id2, size, data, nickname2) || !data)
    {
        Printf(LOG_Error, "[DB] Error: Login_GetCharacter(\"%s\", %u, %u, <size>, <data>, <nickname>).\n", login.c_str(), id1, id2);
        return 0xBADFACE0;
    }

    size_t n1w = nickname1.find_first_of('|');
    if(n1w != nickname1.npos) nickname1.erase(n1w);
    if(nickname1 != nickname2)
    {
        Printf(LOG_Hacking, "[CS] %s - Hacking: tried to change nickname from \"%s\" to \"%s\"!\n", login.c_str(), nickname2.c_str(), nickname1.c_str());
        return 0xBADFACE2;
    }

    SESSION_AddLogin(id1, id2);

    Packet pack;
    pack << (uint8_t)0xDD;
    pack << (uint32_t)(size + nickname.length() + login.length() + 1 + 4 * 7 + 5 - 5 - 5);
    pack << (uint32_t)id1 << (uint32_t)id2;
    pack << (uint32_t)login.length();
    pack << (uint32_t)nickname.length();
    pack << (uint32_t)size;
    pack << (uint32_t)sex;
    pack.AppendData((uint8_t*)data, size);
    pack.AppendData((uint8_t*)login.c_str(), login.length());
    pack.AppendData((uint8_t*)nickname.c_str(), nickname.length());

    delete[] data;

    if(SOCK_SendPacket(conn->Socket, pack, conn->Version) != 0)
    {
        SESSION_DelLogin(id1, id2);
        return 0xBADFACE1;
    }

    return 0;
}
Example #6
0
bool SVCMD_Welcome(ServerConnection* conn)
{
    Packet pack;
    pack << (uint8_t)0xD5;
    /*
    if((conn->Parent->Info.ServerCaps & SERVER_CAP_SOFTCORE) != SERVER_CAP_SOFTCORE)
        pack << (uint32_t)Config::HatID;
    else pack << (uint32_t)Config::HatIDSoftcore;*/
    /*
    if (conn->Parent->Info.ServerMode & SVF_SOFTCORE)
        pack << (uint32_t)Config::HatIDSoftcore;
    else if (conn->Parent->Info.ServerMode & SVF_SANDBOX)
        pack << (uint32_t)Config::HatIDSandbox;
    else pack << (uint32_t)Config::HatID;*/
    pack << (uint32_t)Config::HatID;
    pack << (uint32_t)1;

    return (SOCK_SendPacket(conn->Socket, pack, conn->Version) == 0);
}
Example #7
0
void RunCommand(byte* _this, byte* player, const char* ccommand, uint32_t rights, bool console)
{
    if(!ccommand) return;
    if(ccommand[0] != '#') return;

    std::string command(ccommand);
    command = Trim(command);

    std::string rawcmd = command;

    size_t spacepos = command.find_first_of(' ');
    if(spacepos != std::string::npos)
        rawcmd.erase(spacepos);

    if(rawcmd == "#mapinfo")
    {
		const char* map_file = Config::CurrentMapName.c_str();
		const char* map_name = Config::CurrentMapTitle.c_str();

		uint32_t tme = zxmgr::GetCurrentMapTime()/1000;
		uint32_t tm_h = tme / 3600;
		uint32_t tm_m = tme / 60 - tm_h * 60;
		uint32_t tm_s = tme - (tm_h * 3600 + tm_m * 60);
		tme = zxmgr::GetTotalMapTime()*60;
		uint32_t tt_h = tme / 3600;
		uint32_t tt_m = tme / 60 - tt_h * 60;
		uint32_t tt_s = tme - (tt_h * 3600 + tt_m * 60);

        std::string time_left = "infinite";
        if(!Config::Suspended && zxmgr::GetTotalMapTime() != 0x7FFFFFFF) time_left = Format("%u:%02u:%02u", tt_h, tt_m, tt_s);

        if(player) zxmgr::SendMessage(player, "map: \"%s\" in \"%s\", time elapsed: %u:%02u:%02u, time total: %s", map_name, map_file, tm_h, tm_m, tm_s, time_left.c_str());
        else if(console) Printf("Map: \"%s\" in \"%s\", time elapsed: %u:%02u:%02u, time total: %s", map_name, map_file, tm_h, tm_m, tm_s, time_left.c_str());
        goto ex;
    }

    if(rights & GMF_CMD_CHAT)
    {
        if(command.find("#@") == 0)
        {
            command.erase(0, 2);
            std::string what = "";
            if(!player || console) what = Format("[broadcast] <server%u>: %s", Config::ServerID, command.c_str());
            else if(player) what = Format("[broadcast] %s: %s", *(const char**)(player + 0x18), command.c_str());
            else what = Format("[broadcast] %s", command.c_str());
            if(!NetCmd_Broadcast(what)) NetHat::Connected = false;
            goto ex;
        }
        else if(command.find("#!") == 0)
        {
            command.erase(0, 2);
            if(!player || console) zxmgr::SendMessage(NULL, "<server>: %s", command.c_str());
            else if(player) zxmgr::SendMessage(NULL, "%s: %s", *(const char**)(player + 0x18), command.c_str());
            else zxmgr::SendMessage(NULL, command.c_str());
            goto ex;
        }
    }

    if(rights & GMF_CMD_KICK)
    {
        if(rawcmd == "#kick")
        {
            command.erase(0, 5);
            command = TrimLeft(command);
			byte* target = zxmgr::FindByNickname(command.c_str());

			if(target) zxmgr::Kick(target, false);
            goto ex;
        }
        else if(rawcmd == "#kickme")
        {
            if(!player || console)
            {
                Printf("This command may not be used from the console.");
                goto ex;
            }

            if(player) zxmgr::Kick(player, true);
            goto ex;
        }
		else if(rawcmd == "#kickall")
		{
			zxmgr::KickAll(NULL);
			goto ex;
		}
        else if(rawcmd == "#kick_silent")
        {
            command.erase(0, 12);
            command = TrimLeft(command);
            byte* target = zxmgr::FindByNickname(command.c_str());

            if(target) zxmgr::Kick(target, true);
            goto ex;
        }
        else if(rawcmd == "#disconnect")
        {
            command.erase(0, 11);
            command = TrimLeft(command);
            byte* target = zxmgr::FindByNickname(command.c_str());

            if(target) zxmgr::Disconnect(target);
            goto ex;
        }
    }

    if(rights & GMF_CMD_INFO)
    {
        if(rawcmd == "#locate")
        {
            command.erase(0, 7);
            command = TrimLeft(command);
			byte* target = zxmgr::FindByNickname(command.c_str());

            if(target && *(byte**)(target + 0x38))
            {
                uint32_t p_x = *(uint8_t*)(*(uint32_t*)(*(byte**)(target + 0x38) + 0x10));
                uint32_t p_y = *(uint8_t*)(*(uint32_t*)(*(byte**)(target + 0x38) + 0x10) + 1);

                if(!player || console)
                    Printf("%s (%u:%u)", *(const char**)(target + 0x18), p_x, p_y);
                else if(player)
                    zxmgr::SendMessage(player, "%s (%u:%u)", *(const char**)(target + 0x18), p_x, p_y);
            }
            goto ex;
        }
        else if(rawcmd == "#info")
        {
            command.erase(0, 5);
            command = TrimLeft(command);
            byte* target = zxmgr::FindByNickname(command.c_str());

            if(!target) goto ex;
            if(!*(byte**)(target + 0x38)) goto ex;

            const char* p_charname = *(const char**)(target + 0x18);
            const char* p_logname = *(const char**)(target + 0x0A78);
            byte* netinf = zxmgr::GetNetworkStruct(target);
            bool p_connected = (netinf);
            const char* p_address = "n/a";
            if(p_connected) p_address = (const char*)(netinf + 8);

            std::string p_state;
            if(p_connected) p_state = Format("connected (%s)", p_address);
            else p_state = "disconnected";

            byte* unit = *(byte**)(target + 0x38);

            uint8_t p_body      = *(uint8_t*)(unit + 0x84);
            uint8_t p_reaction  = *(uint8_t*)(unit + 0x86);
            uint8_t p_mind      = *(uint8_t*)(unit + 0x88);
            uint8_t p_spirit    = *(uint8_t*)(unit + 0x8A);

            const char* p_strong = (vd2_CheckStrong(unit) ? "yes" : "no");

            if(!player || console)
            {
                Printf("nickname: \"%s\", login: \"%s\", state: %s, stats: [%u,%u,%u,%u], strong: %s",
                       p_charname, p_logname, p_state.c_str(),
                       p_body, p_reaction, p_mind, p_spirit, p_strong);
            }
            else if(player)
            {
                zxmgr::SendMessage(player, "nickname: \"%s\", login: \"%s\", state: %s, stats: [%u,%u,%u,%u], strong: %s\n",
                                    p_charname, p_logname, p_state.c_str(),
                                    p_body, p_reaction, p_mind, p_spirit, p_strong);
            }

            goto ex;
        }
		else if(rawcmd == "#scan")
		{
			if(!player) goto ex;
			byte* unit = *(byte**)(player + 0x38);
			if(!unit) goto ex;

			SR_DumpToFile(player);
			goto ex;
		}
    }

    if(rights & GMF_CMD_KILL)
    {
        if(rawcmd == "#kill")
        {
            command.erase(0, 5);
            command = TrimLeft(command);
            byte* target = zxmgr::FindByNickname(command.c_str());

            if(target)
            {
                uint32_t tri = 0;
                if(!*(uint32_t*)(target + 0x2C))
                    tri = *(uint32_t*)(target + 0x14);

                if(CHECK_FLAG(tri, GMF_ANY))
                {
                    if(((tri & GMF_GODMODE) &&
                        (rights & GMF_GODMODE_ADMIN)) ||
                        (tri & GMF_GODMODE_ADMIN)) goto ex;
                }

				zxmgr::Kill(target, player);
            }
            goto ex;
        }
		else if(rawcmd == "#murder")
		{
			command.erase(0, 7);
			command = TrimLeft(command);
            byte* target = zxmgr::FindByNickname(command.c_str());

            if(target)
            {
                uint32_t tri = 0;
                if(!*(uint32_t*)(target + 0x2C))
                    tri = *(uint32_t*)(target + 0x14);

                if(CHECK_FLAG(tri, GMF_ANY))
                {
                    if((((tri & GMF_GODMODE) &&
                       !(rights & GMF_GODMODE_ADMIN)) ||
                        (tri & GMF_GODMODE_ADMIN)) && target != player) goto ex;
                }

				zxmgr::Kill(target, player);
				byte* unit = *(byte**)(target + 0x38);
				if(unit && target != player)
					DropEverything(unit, true);
			}
			goto ex;
		}
        else if(rawcmd == "#killall")
        {
            zxmgr::KillAll(player, false);
        }
        else if(rawcmd == "#killai")
        {
            zxmgr::KillAll(player, true);
        }
    }

    if(rights & GMF_CMD_PICKUP)
    {
        if(rawcmd == "#pickup")
        {
            if(!player || console)
            {
                Printf("This command may not be used from the console.");
                goto ex;
            }

            if(player)
            {
                cheat_codes_2(player, ccommand);
            }
            goto ex;
        }
    }

    if(rights & GMF_CMD_SUMMON)
    {
        if(rawcmd == "#summon")
        {
            if(!player || console)
            {
                Printf("This command may not be used from the console.");
                goto ex;
            }

            if(player && *(byte**)(player + 0x38))
            {
                command.erase(0, 7);
                command = Trim(command);
				if(!command.length()) goto ex;

                uint32_t count = 1;
                size_t fsp = command.find_first_of(" ");
                if(fsp != std::string::npos)
                {
                    std::string intstr = command;
                    intstr.erase(fsp);
                    if(CheckInt(intstr))
                    {
                        command.erase(0, fsp + 1);
                        command = TrimLeft(command);
                        count = StrToInt(intstr);
                        if(!count) count = 1;
                    }
                }

				if(!command.length()) goto ex;
                for(uint32_t i = 0; i < count; i++)
                {
					byte* unit = zxmgr::Summon(player, command.c_str(), *(byte**)(0x00642C2C), false, NULL);
                    //byte* unit = Map::CreateUnitForEx(player, command.c_str(), false);
                    //zxmgr::SendMessage(NULL, "what: %02X\n", *(uint8_t*)(*(byte**)(unit + 0x1C4) + 0x78));
                    //Unit::SetSpells(unit);
                }
            }
        }
    }

    if(rights & GMF_CMD_SET)
    {
        if(rawcmd == "#nextmap")
        {
            zxmgr::NextMap();
            goto ex;
        }
        else if(rawcmd == "#prevmap")
        {
            zxmgr::PrevMap();
            goto ex;
        }
        else if(rawcmd == "#resetmap")
        {
            if(Config::Suspended)
            {
                zxmgr::SetTotalMapTime(Config::OriginalTime);
                Config::Suspended = false;
            }
            zxmgr::ResetMap();
            goto ex;
        }
        else if(rawcmd == "#shutdown")
        {
            TerminateProcess(GetCurrentProcess(), 100);
            goto ex;
        }
        else if(rawcmd == "#suspend")
        {
            if(!Config::Suspended)
            {
                Config::OriginalTime = zxmgr::GetTotalMapTime();
                zxmgr::SetTotalMapTime(0x7FFFFFFF);

                if(!player || console) Printf("Map timer suspended.");
                else if(player) zxmgr::SendMessage(player, "suspend: map timer suspended.");
            }
            else
            {
                bool change_map = false;
                uint32_t cur_time = zxmgr::GetCurrentMapTime() / 60000;
                if(cur_time >= Config::OriginalTime) change_map = true;

                zxmgr::SetTotalMapTime(Config::OriginalTime);
                Config::OriginalTime = 0;

                if(!player || console) Printf("Map timer released.");
                else if(player) zxmgr::SendMessage(player, "suspend: map timer released.");

                if(change_map)
                {
                    Printf("Note: map timer beyond total map time. Changing map...");
                    zxmgr::NextMap();
                }
            }

            Config::Suspended = !Config::Suspended;
            goto ex;
        }
        else if(rawcmd == "#set" && (command.find("#set mode") == 0))
        {
            command.erase(0, 9);
            command = Trim(command);

            if(!command.length())
            {
                if(!player || console) Printf("Mode is set to %08X.", Config::ServerFlags);
                else if(player) zxmgr::SendMessage(player, "mode is set to %08X", Config::ServerFlags);
            }
            else
            {
                int32_t add_flags = 0;
                if(command[0] == '+') add_flags = 1;
                else if(command[0] == '-') add_flags = -1;
                else if(command[0] == '=') add_flags = 0;
                else goto ex;

                if(add_flags != 0) command.erase(0, 1);
                if(command[0] != '=') goto ex;
                command.erase(0, 1);

                uint32_t old_mode = Config::ServerFlags;

                uint32_t flags = ParseFlags(TrimLeft(command));
                if(add_flags == -1) Config::ServerFlags &= ~flags;
                else if(add_flags == 1) Config::ServerFlags |= flags;
                else Config::ServerFlags = flags;

                if(old_mode != Config::ServerFlags)
                {
                    if(!player || console) Printf("Mode is set to %08X (was: %08X).", Config::ServerFlags, old_mode);
                    else if(player) zxmgr::SendMessage(player, "mode is set to %08X (was: %08X)", Config::ServerFlags, old_mode);

					if(Config::ServerFlags & SVF_SOFTCORE)
					{
						MAX_SKILL = 110;
						Config::ServerCaps |= SVC_SOFTCORE;
					}
					else
					{
						MAX_SKILL = 100;
						Config::ServerCaps &= ~SVC_SOFTCORE;
					}
                }
                else
                {
                    if(!player || console) Printf("Mode is set to %08X.", Config::ServerFlags);
                    else if(player) zxmgr::SendMessage(player, "mode is set to %08X", Config::ServerFlags);
                }
            }

            goto ex;
        }
        else if(command.find("#speed") == 0)
        {
            command.erase(0, 6);
            command = Trim(command);
            if(!CheckInt(command)) goto ex;
            uint32_t speed = StrToInt(command);
            if(!speed) speed = 1;
            if(speed > 8) speed = 8;

			zxmgr::SetSpeed(speed);
            goto ex;
        }
		else if(rawcmd == "#mapwide")
		{
			if(!player || console)
			{
				Printf("This command may not be used from the console.");
				goto ex;
			}

			uint32_t what = 7; // blizzard
			
			command.erase(0, 8);
			command = Trim(command);
			if(CheckInt(command) && command.length()) what = StrToInt(command);

			byte* unit = *(byte**)(player + 0x38);
			if(!unit) goto ex;

			uint8_t p_x = *(uint8_t*)(*(byte**)(unit + 0x10));
            uint8_t p_y = *(uint8_t*)(*(byte**)(unit + 0x10) + 1);

            uint32_t p_mapwidth = *(uint32_t*)(*(uint32_t*)(0x006B16A8) + 0x50000);
            uint32_t p_mapheight = *(uint32_t*)(*(uint32_t*)(0x006B16A8) + 0x50004);

			uint32_t step_x = 1;
			uint32_t step_y = 1;

			switch(what)
			{
			case 7: // blizzard
				step_x = 1;
				step_y = 1;
				break;
			case 14: // darkness
			case 15: // light
			case 6: // poison cloud
				step_x = 1;
				step_y = 1;
				break;
			case 9: // acid steam
				step_x = 1;
				step_y = 1;
				break;
			case 2: // fire ball
				step_x = 1;
				step_y = 1;
				break;
			case 3: // fire wall
				step_x = 1;
				step_y = 1;
				break;
			default: // any other spell is forbidden
				goto ex;			
			}

			uint32_t count_x = 51;
			uint32_t count_y = 51;

			int32_t start_x = p_x - 25;
			int32_t start_y = p_y - 25;

			for(int32_t i = start_x; i <= start_x+count_x; i++)
			{
				for(int32_t j = start_y; j <= start_y+count_y; j++)
				{
					if(i < 8 || i > p_mapwidth-8 ||
						j < 8 || j > p_mapheight-8) continue;
					zxmgr::CastPointEffect(unit, i, j, what);
				}
			}
 
			goto ex;
		}
		else if(rawcmd == "#inn")
		{
			if(!player) goto ex;
			byte* unit = *(byte**)(player + 0x38);
			if(!unit) goto ex;
			byte* item = *(byte**)(unit + 0x74);
			if(!item) goto ex;
			zxmgr::SendMessage(NULL, "%04x", *(uint16_t*)(item+0x40));
			goto ex;
		}
		else if(rawcmd == "#uh")
		{
			if(!player) goto ex;
			SOCKET ps = zxmgr::GetSocket(player);

			Packet testp;
			testp.WriteUInt32(0xBADFACE1);
			SOCK_SendPacket(ps, testp, 0, true);
			goto ex;
		}
    }

    if(rights & GMF_CMD_CREATE)
    {
        if(rawcmd == "#create")
        {
            if(!player || console)
            {
                Printf("This command may not be used from the console.");
                goto ex;
            }

            if(!*(byte**)(player + 0x38)) goto ex;

            command.erase(0, 7);
            command = Trim(command);

            uint32_t count = 1;
            size_t fsp = command.find_first_of(" ");
            if(fsp != std::string::npos)
            {
                std::string intstr = command;
                intstr.erase(fsp);
                if(CheckInt(intstr))
                {
                    command.erase(0, fsp + 1);
                    command = TrimLeft(command);
                    count = StrToInt(intstr);
                    if(!count) count = 1;
                }
            }

            if(ToLower(command) == "gold")
            {
                zxmgr::GiveMoney(player, count, 1);
            }
            else
            {
                if(command.find("{") != std::string::npos)
                {
                    for(uint32_t i = 0; i < count; i++)
					{
						byte* t_item = zxmgr::ConstructItem(command);
						if(!t_item) goto ex;
						// special case for scrolls/potions
						if(*(uint8_t*)(t_item + 0x58) == 0 && *(uint8_t*)(t_item + 0x45) == 0 && *(uint8_t*)(t_item + 0x46) == 0 && *(uint16_t*)(t_item + 0x4A) == 1)
						{
							*(uint16_t*)(t_item + 0x42) = count;
							zxmgr::GiveItemTo(t_item, player);
							break;
						}

						*(uint16_t*)(t_item + 0x42) = 1;
	                    zxmgr::GiveItemTo(t_item, player);
					}
                }
                else
                {
					byte* t_item = zxmgr::ConstructItem(command);
					if(!t_item) goto ex;
                    *(uint16_t*)(t_item + 0x42) = count;
                    zxmgr::GiveItemTo(t_item, player);
                }
            }

            zxmgr::UpdateUnit(*(byte**)(player + 0x38), player, 0xFFFFFFFF, 0xFFB, 0, 0);
            goto ex;
        }
    }

	// #modify player +god:
	//  включает годмод. годмод сбрасывается при выходе игрока с карты ИЛИ при выходе установившего ГМа с карты.
	// #modify player ++god: годмод НЕ сбрасывается при выходе ГМа с карты.
	// #modify player -god (--god): отменяет команды выше. количество минусов в данном случае значения не имеет.
	// #modify player +spells: временно добавляет все заклинания. при выходе игрока или установившего ГМа с карты заклинания
    //  сбрасываются обратно на старую книгу. также можно сбросить заклинания через #modify player -spells.
	// #modify player -spells: если книга заклинаний игрока не менялась, временно удаляет все заклинания.
	//  при выходе игрока или ГМа с карты заклинания возвращаются в норму. эффект отменяется через #modify player +spells.
	// #modify player ++spells: то же самое, но навсегда. сбросить заклинания обратно невозможно.
	// #modify player --spells: см. выше про -spells.

	if(rights & GMF_CMD_MODIFY)
	{
		if(rawcmd == "#modify")
		{
			command.erase(0, 7);
			command = Trim(command);

			byte* target = NULL;
			std::string targetname = "";
			for(size_t i = 0; i < command.length(); i++)
			{
				targetname += command[i];
				if(targetname == "self") continue;
				target = zxmgr::FindByNickname(targetname.c_str());
				if(target) break;
			}
			
			if(!target)
			{
				std::string lowercommand = ToLower(command);
				if(lowercommand.find("self") == 0)
				{
					targetname = "self";
					target = player;
				}
				else goto ex;
			}

			Player* pi = PI_Get(target);
			if(!pi) goto ex;

			command.erase(0, targetname.length());
			command = TrimLeft(command);
			if(!command.length()) goto ex;

			int r_change = 0;
			if(command[0] == '+') r_change = 1;
			else if(command[0] == '-') r_change = -1;
			if(!r_change) goto ex;

			command.erase(0, 1);
			if(!command.length()) goto ex;
			if(command[0] == '+') r_change = 2;
			else if(command[0] == '-') r_change = -2;
			
			if(r_change == 2 || r_change == -2)
				command.erase(0, 1);

			command = ToLower(TrimLeft(command));

			byte* unit = *(byte**)(target + 0x38);
			
			if(command == "god")
			{
				if(r_change > 0)
				{
					pi->GodMode = true;
					if(r_change == 1) pi->GodSetter = player;
					else pi->GodSetter = NULL;
				}
				else if(r_change < 0)
				{
					pi->GodMode = false;
					pi->GodSetter = NULL;
				}
			}
			else if(command == "spells" && unit)
			{
				if(r_change > 0)
				{
					if(pi->SetSpells == -1 && r_change != 2) // prev. command removed spells
					{
						pi->SetSpells = 0;
						zxmgr::SetSpells(unit, pi->LastSpells);
						pi->LastSpells = 0;
					}
					else
					{
						if(r_change == 1)
						{
							pi->SetSpells = 1;
							pi->SpellSetter = player;
						}
						else
						{
							pi->SetSpells = 0;
							pi->SpellSetter = NULL;
						}

						pi->LastSpells = zxmgr::GetSpells(unit);
						zxmgr::SetSpells(unit, 0xFFFFFFFF);
					}
				}
				else if(r_change < 0)
				{
					if(pi->SetSpells == 1 && r_change != -2) // prev. command added spells
					{
						pi->SetSpells = 0;
						zxmgr::SetSpells(unit, pi->LastSpells);
						pi->LastSpells = 0;
					}
					else
					{
						if(r_change == -1)
						{
							pi->SetSpells = 1;
							pi->SpellSetter = player;
						}
						else
						{
							pi->SetSpells = 0;
							pi->SpellSetter = NULL;
						}

						pi->SetSpells = -1;
						pi->LastSpells = zxmgr::GetSpells(unit);
						zxmgr::SetSpells(unit, 0);
					}
				}

				zxmgr::UpdateUnit(unit, 0, 0xFFFFFFFF, 0xFFB, 0, 0);
			}
			else if(command == "knowledge" && unit)
			{
				if(r_change > 0)
				{

				}
				else if(r_change < 0)
				{

				}
			}
		}
	}

ex:
    return;
}