• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

How to make your server client 8.61 Tutorial

I compile it But when I run my server players cant attack monsters, why?

Obiously you did something wrong. Some other "known bugs":

* No-autostacking
* Doesn't check bags etc, only hands for blank runes.
 
unfortunately, that's how most container operations work in source. and it's not slow at all.

not slow ? Try to put like 500-1000 bp in bp and make some container action ( npc buy ), your proc/core will go to 100% for sure.
 
Indeed I did something wrong.
The monster bug is fixed on 8.60 but now when I log with 8.55 protocol and I kill a monster my client debugs
How can I fix this? I dont want my server to have autostack or any other 8.60 feature I just want it to be compatible with 8.55-8.60
 
youll have to send different packets checking players client, its possible but I dunno how to return client version in changed network functions
 
Yes, it's true. But the reallybig problem will be with newer maps becasue they will get debug if you want to support 8.5x also.
 
Auto stacking of empty flasks in the same backpack:

potion script (new code is in red text):
Code:
local config = {
	removeOnUse = "no",
	usableOnTarget = "yes", -- can be used on target? (fe. healing friend)
	splashable = "no",
	realAnimation = "no", -- make text effect visible only for players in range 1x1
	healthMultiplier = 1.0,
	manaMultiplier = 1.0
}

config.removeOnUse = getBooleanFromString(config.removeOnUse)
config.usableOnTarget = getBooleanFromString(config.usableOnTarget)
config.splashable = getBooleanFromString(config.splashable)
config.realAnimation = getBooleanFromString(config.realAnimation)

local POTIONS = {
	[8704] = {empty = 7636, splash = 2, health = {50, 100}}, -- small health potion
	[7618] = {empty = 7636, splash = 2, health = {100, 200}}, -- health potion
	[7588] = {empty = 7634, splash = 2, health = {200, 400}, level = 50, vocations = {3, 4, 7, 8}, vocStr = "knights and paladins"}, -- strong health potion
	[7591] = {empty = 7635, splash = 2, health = {500, 700}, level = 80, vocations = {4, 8}, vocStr = "knights"}, -- great health potion
	[8473] = {empty = 7635, splash = 2, health = {800, 1000}, level = 130, vocations = {4, 8}, vocStr = "knights"}, -- ultimate health potion

	[7620] = {empty = 7636, splash = 7, mana = {70, 130}}, -- mana potion
	[7589] = {empty = 7634, splash = 7, mana = {110, 190}, level = 50, vocations = {1, 2, 3, 5, 6, 7}, vocStr = "sorcerers, druids and paladins"}, -- strong mana potion
	[7590] = {empty = 7635, splash = 7, mana = {200, 300}, level = 80, vocations = {1, 2, 5, 6}, vocStr = "sorcerers and druids"}, -- great mana potion

	[8472] = {empty = 7635, splash = 3, health = {200, 400}, mana = {110, 190}, level = 80, vocations = {3, 7}, vocStr = "paladins"} -- great spirit potion
}

local exhaust = createConditionObject(CONDITION_EXHAUST)
setConditionParam(exhaust, CONDITION_PARAM_TICKS, (getConfigInfo('timeBetweenExActions') - 100))

function onUse(cid, item, fromPosition, itemEx, toPosition)
	local potion = POTIONS[item.itemid]
	if(not potion) then
		return false
	end

	if(not isPlayer(itemEx.uid) or (not config.usableOnTarget and cid ~= itemEx.uid)) then
		if(not config.splashable) then
			return false
		end

		if(toPosition.x == CONTAINER_POSITION) then
			toPosition = getThingPos(item.uid)
		end

		doDecayItem(doCreateItem(2016, potion.splash, toPosition))
		doTransformItem(item.uid, potion.empty)
		return true
	end

	if(hasCondition(cid, CONDITION_EXHAUST_HEAL)) then
		doPlayerSendDefaultCancel(cid, RETURNVALUE_YOUAREEXHAUSTED)
		return true
	end

	if(((potion.level and getPlayerLevel(cid) < potion.level) or (potion.vocations and not isInArray(potion.vocations, getPlayerVocation(cid)))) and
		not getPlayerCustomFlagValue(cid, PLAYERCUSTOMFLAG_GAMEMASTERPRIVILEGES))
	then
		doCreatureSay(itemEx.uid, "Only " .. potion.vocStr .. (potion.level and (" of level " .. potion.level) or "") .. " or above may drink this fluid.", TALKTYPE_ORANGE_1)
		return true
	end

	local health = potion.health
	if(health and not doCreatureAddHealth(itemEx.uid, math.ceil(math.random(health[1], health[2]) * config.healthMultiplier))) then
		return false
	end

	local mana = potion.mana
	if(mana and not doPlayerAddMana(itemEx.uid, math.ceil(math.random(mana[1], mana[2]) * config.manaMultiplier))) then
		return false
	end

	doSendMagicEffect(getThingPos(itemEx.uid), CONST_ME_MAGIC_BLUE)
	if(not realAnimation) then
		doCreatureSay(itemEx.uid, "Aaaah...", TALKTYPE_ORANGE_1)
	else
		for i, tid in ipairs(getSpectators(getCreaturePosition(cid), 1, 1)) do
			if(isPlayer(tid)) then
				doCreatureSay(itemEx.uid, "Aaaah...", TALKTYPE_ORANGE_1, false, tid)
			end
		end
	end

	doAddCondition(cid, exhaust)

[B][COLOR="Red"]	local v = getItemParent(item.uid)
	doChangeTypeItem(item.uid, item.type - 1)[/COLOR][/B]
	if(not potion.empty or config.removeOnUse) then
		return true
	end

[B][COLOR="Red"]	if v.uid == 0 then
		local hack
		if fromPosition.y == CONST_SLOT_LEFT and getPlayerSlotItem(cid, CONST_SLOT_RIGHT).uid == 0 then
			hack = doPlayerAddItem(cid, 2148, 1)
		end
		doPlayerAddItem(cid, potion.empty, 1)
		if hack then
			doRemoveItem(hack)
		end
		return true
	end

	local size = getContainerSize(v.uid)
	for i = 0, size-1 do
		local tmp = getContainerItem(v.uid, i)
		if tmp.itemid == potion.empty and tmp.type < 100 then
			return getPlayerFreeCap(cid) >= getItemInfo(potion.empty).weight and doChangeTypeItem(tmp.uid, tmp.type + 1) or doPlayerAddItem(cid, potion.empty, 1)
		end
	end

	if getContainerSize(v.uid) < getContainerCap(v.uid) then
		doAddContainerItem(v.uid, potion.empty)
	else
		doPlayerAddItem(cid, potion.empty, 1)
	end[/COLOR][/B]
	return true
end
luascript.cpp:
Code:
int32_t LuaScriptInterface::luaGetItemParent(lua_State* L)
{
	//getItemParent(uid)
	ScriptEnviroment* env = getEnv();

	Item* item = env->getItemByUID(popNumber(L));
	if(!item)
	{
		errorEx(getError(LUA_ERROR_ITEM_NOT_FOUND));
		lua_pushnil(L);
		return 1;
	}

	Item* container = item->getParent()->getItem();
	pushThing(L, container, env->addThing(container));
	return 1;
}

	//getItemParent(uid)
	lua_register(m_luaState, "getItemParent", LuaScriptInterface::luaGetItemParent);
luascript.h:
Code:
		static int32_t luaGetItemParent(lua_State* L);
 
Last edited:
Nice, Cyko.

For TfS 0.4:

*luascript.cpp

Replace:
Code:
int32_t LuaScriptInterface::luaGetItemParent(lua_State* L)
to
Code:
int32_t LuaInterface::luaGetItemParent(lua_State* L)
 
damn, Cyko thanks for that code(and potion script become quite bigger as I expected)

i tried to optimize, but no success :p

i'm still not sure whether it behaves in cipbia like this..
if the backpack is full, where does the flask go?
into the main backpack, or into the first stack of empty flasks it finds (if any)?
the same question goes for potions that you use 'from ground'.
 
dunno, not tested yet(do you have char with funds needed for deep testing or I have to test it? if I have to, tell me everything what you need to know)

I'mpretty sure that normal doPlayerAddItem(or something...) work fine, cause when I filled up my potion parcel with my eq vial appeared in my hand
 
buy 2 potions, fill up the container and use 1 of them? :p but i also think it's normal addItem

okay, edited script
 
well, its a bit bugged, cause it doesnt leave vial if you use last potion in stack

also I wonder why if you have 1 pot in full bp vial goes somewhere else when you use that pot

I think it should be: if in container with pot there is no potion.empty or potion.empty stacks are full and you use last pot use transform instead of reducing ammount(will be realistic I guess, dunno how its in global but...)

move
Code:
local v = getItemParent(item.uid)
before
Code:
doChangeTypeItem(item.uid, item.type - 1)
and change
Code:
if(not potion.empty or item.type == 1 or config.removeOnUse) then
to
Code:
if(not potion.empty or  config.removeOnUse) then
, it should help I guess

yeah, helped for containers, but if I use pot in hand on left side of screen(right one?) vial appear in second hand, to fix it some additional checks are needed(if parent isnt item check if slotitem.uid==item.uid and item.type==1 then doPlayerAddSlotItem?)
 
Last edited:
yea, i just realized and fixed. hate to make hacks for things like these hands.
Code:
	if v.uid == 0 then
		local hack
		if fromPosition.y == CONST_SLOT_LEFT and getPlayerSlotItem(cid, CONST_SLOT_RIGHT).uid == 0 then
			hack = doPlayerAddItem(cid, 2148, 1)
		end
		doPlayerAddItem(cid, potion.empty, 1)
		doRemoveItem(hack)
		return true
	end
?
 
Last edited:
fix'd
or no, hell no...

ok, fix'd as far as I know
Code:
bugged

just if you have vial in right hand, left hand empty and you use pot from pb it goes to left hand(but situation with vial in one of slots and another slot empty and full bp is almost unreal), just before doPlayerAddItem you have to loop that 3 slots and check if any can handle one more vial, if so add vial to it, damn, so easy script, so much stupid hacks
 
Last edited:
Back
Top