|
-
Apprentice
[G2] Block item to sell?
Hello. It's possible to block item(instance aaa) to sell during trade with npc? Because actually when i try sell it i don't get actually currency, but it gonna duplikate in trader EQ. I have LeGo and Ikarus. I know engine block itmi_gold, but how use it to block other item?
-
Zitat von dorumia
Hello. It's possible to block item(instance aaa) to sell during trade with npc? Because actually when i try sell it i don't get actually currency, but it gonna duplikate in trader EQ. I have LeGo and Ikarus. I know engine block itmi_gold, but how use it to block other item?
Are items with flag ITEM_MISSION excluded from trading? I don't quite remember...
-
Apprentice
No. If item have ITEM_MISSION flag, he can be selled(ex. Old Coin)
-
Zitat von dorumia
No. If item have ITEM_MISSION flag, he can be selled(ex. Old Coin)
you're right; we get that functionality through a hook:
https://forum.worldofplayers.de/foru...1#post24695536
Code:
/*
* Dictate which items may be sold
* Written by Frank-95 https://forum.worldofplayers.de/forum/threads/?p=24695536
*
* Initialize with CheckSellingItems_Init() in Init_Global
* Compatible with Gothic 2 only
*/
func int CanSellItem(var C_Item itm) {
if <your condition> {
//Print("I should probably keep this");
B_Say(hero, NULL, "$DONTKNOW"); //Hmm ... No ...
return FALSE;
};
// .. more ..
return TRUE;
};
func void CheckSellingItems_Init() {
const int oCViewDialogTrade__OnTransferLeft = 6862912; //0x68B840
HookEngineF(oCViewDialogTrade__OnTransferLeft, 6, CheckSellingItems);
MemoryProtectionOverride(oCViewDialogTrade__OnTransferLeft + 6, 4);
};
func void CheckSellingItems() {
const int oCViewDialogTrade__OnTransferLeft = 6862912; //0x68B840
MEM_Info("Called CheckSellingItems()");
var oCNpc her; her = Hlp_GetNpc(hero);
var C_Item itm;
itm = _^(List_GetS(her.inventory2_oCItemContainer_contents, her.inventory2_oCItemContainer_selectedItem + 2));
if (CanSellItem(itm)) {
MEM_WriteByte(oCViewDialogTrade__OnTransferLeft + 6, 106); // push
} else {
MEM_WriteByte(oCViewDialogTrade__OnTransferLeft + 6, 195); // retn
};
};
-
-
Nur falls sich jemand wundert wo genau der Code herkommt. Der ist eine überarbeitete Version des bereits verlinkten Ansatzes. Gepostet wurde der Code hier. Nur als Referenz, denn dort wurde der Code noch weiter diskutiert und noch andere, verwandte Skripte gepostet (inkl. CanDropItem, CanSellItem, CanTransferItemToContainer).
Ich editiere mal diese Beiträge und füge jeweils Verlinkungen im Kommentarblock hinzu. Dann findet man immer ihren Ursprung, sollten mal Fragen aufkommen. Ist denke ich eine gute Angewohnheit beim Teilen von fertigem Skripten.
Geändert von mud-freak (08.11.2020 um 10:06 Uhr)
-
Apprentice
Thanks everyone, it's work now. Nice to know here are people, who want help =)
Btw. it's possible with Ikarus to set collision in spell? Because i have a few added spell, which don't init other npc react(ex. when i hit npc with spell, other said "Oh god, fight" and back to routine). And when i kill npc with this spell, other npc don't attack me. And i hear it's need to hook function GetSpellType and set collision. It's true or i just get tricked?
Geändert von dorumia (08.11.2020 um 10:42 Uhr)
Grund: New question
-
Zitat von dorumia
Btw. it's possible with Ikarus to set collision in spell? Because i have a few added spell, which don't init other npc react(ex. when i hit npc with spell, other said "Oh god, fight" and back to routine). And when i kill npc with this spell, other npc don't attack me. And i hear it's need to hook function GetSpellType and set collision. It's true or i just get tricked?
No need to hook anything. This should work out of the box. It may be related to how the damage is dealt. There may be a problem with how you created the spell. If you share the changes/additions you made so far, maybe someone will spot an issue or what's missing.
-
Apprentice
Code:
const int SPL_COST_Pyrokinesis1 = 10;
const int SPL_DAMAGE_Pyrokinesis1 = 30;
instance Spell_Pyrokinesis1(C_Spell_Proto)
{
time_per_mana = 500;
damage_per_level = SPL_DAMAGE_Pyrokinesis1;
spellType = SPELL_BAD;
damagetype = DAM_MAGIC;
targetCollectAlgo = TARGET_COLLECT_FOCUS_FALLBACK_NONE;
targetCollectRange = 1000;
targetCollectType = TARGET_TYPE_NPCS;
};
func int Spell_Logic_Pyrokinesis1(var int manaInvested)
{
if(!Npc_IsInState(other,zs_psidefense) || Npc_IsPlayer(other))
&& (other.guild < GIL_SEPERATOR_HUM)
{
if (Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else if (self.attribute[ATR_MANA] >= SPL_COST_Pyrokinesis1)
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_COST_Pyrokinesis1;
}
else //nicht genug Mana
{
return SPL_SENDSTOP;
};
Npc_ClearAIQueue(other);
AI_StandupQuick(other);
AI_StartState(other,zs_psidefense,0,"");
Npc_ChangeAttribute (other, ATR_HITPOINTS, -SPL_DAMAGE_Pyrokinesis1);
}
else if(Npc_IsInState(other,zs_psidefense))
&& (other.guild < GIL_SEPERATOR_HUM)
{
if (Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else if (self.attribute[ATR_MANA] >= SPL_COST_Pyrokinesis1)
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_COST_Pyrokinesis1;
}
else //nicht genug Mana
{
return SPL_SENDSTOP;
};
Npc_ChangeAttribute (other, ATR_HITPOINTS, -SPL_DAMAGE_Pyrokinesis1);
if(other.attribute[ATR_Hitpoints] <= 0)
{
B_GivePlayerXP (other.level * XP_PER_VICTORY);
Npc_ClearAIQueue(other);
AI_Standup(other);
return SPL_SENDCAST;
}
else if (self.attribute[ATR_MANA] < 10)
{
Npc_ClearAIQueue(other);
AI_Standup(other);
return SPL_SENDCAST;
};
}
else
{
if (Npc_GetActiveSpellIsScroll(self) && (self.attribute[ATR_MANA] >= SPL_Cost_Scroll))
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_Cost_Scroll;
}
else if (self.attribute[ATR_MANA] >= SPL_COST_Pyrokinesis1)
{
self.attribute[ATR_MANA] = self.attribute[ATR_MANA] - SPL_COST_Pyrokinesis1;
}
else //nicht genug Mana
{
return SPL_SENDSTOP;
};
Npc_ChangeAttribute (other, ATR_HITPOINTS, -SPL_DAMAGE_Pyrokinesis1);
if(other.attribute[ATR_Hitpoints] <= 0)
{
B_GivePlayerXP (other.level * XP_PER_VICTORY);
Npc_ClearAIQueue(other);
AI_Standup(other);
return SPL_SENDCAST;
}
else if (self.attribute[ATR_MANA] < 10)
{
Npc_ClearAIQueue(other);
AI_Standup(other);
return SPL_SENDCAST;
};
};
return SPL_NEXTLEVEL;
};
func void Spell_Cast_Pyrokinesis1(var int spellLevel)
{
self.aivar[AIV_SelectSpell] += 1;
};
Spell script and under - ZS_PsiDefense.
Code:
func void ZS_PsiDefense()
{
PrintDebugNpc (PD_ZS_CHECK, "ZS_PsiDefense");
Npc_PercEnable (other, PERC_ASSESSDAMAGE , ZS_ReactToDamage);
Npc_PercEnable (other, PERC_ASSESSSTOPMAGIC, B_StopPsiDefense);
if ( !Npc_HasBodyFlag(other, BS_FLAG_INTERRUPTABLE) )
{
PrintDebugNpc (PD_MAGIC, "bodystate not interuptable, standing up...");
AI_StandUp (other);
};
};
func void ZS_PsiDefense_Loop()
{
PrintDebugNpc (PD_ZS_LOOP, "ZS_PsiDefense Loop");
if ( !Npc_IsDead(other) && !Npc_IsInState(other, ZS_Unconscious) && (other.guild < GIL_SEPERATOR_HUM) && !C_BodystateContains(other,BS_SWIM) && !C_BodystateContains(other,BS_DIVE) )
{
PrintDebugNpc (PD_MAGIC, "...NSC ist nicht bewußtlos / tot / schwimmend / tauchend");
AI_PlayAni (other, "S_CON_VICTIM");
};
};
func void ZS_PsiDefense_End()
{
PrintDebugNpc (PD_ZS_CHECK, "ZS_PsiDefense End");
};
func void B_StopPsiDefense ()
{
Npc_PercEnable (other, PERC_ASSESSMAGIC, B_AssessMagic); //falls in diesem Frame (während des Ausführens des B_) noch ein neuer Spruch wirkt
Npc_ClearAIQueue(other);
AI_StandUp (other);
if (other.guild < GIL_SEPERATOR_HUM)
{
B_AssessDamage();
AI_ContinueRoutine (other);
}
else
{
Npc_SetTempAttitude (other, ATT_HOSTILE);
AI_ContinueRoutine (other);
};
};
Geändert von dorumia (13.11.2020 um 17:13 Uhr)
-
Apprentice
-
Apprentice
Hi. I have different question in this matter. What if we want to block item to buy? I assume that the function will be looking similar:
Code:
const int oCViewDialogTrade__OnTransferRight = 6863632; //0x68BB10
func void CheckBuyingItems() { her = MEM_CpyInst(hero);
var int contLeft; contLeft = oCItemContainer_GetNextContainerLeft(_@(her.inventory2_vtbl), _@(her.inventory2_vtbl));
if (contLeft)
{
var int itemPtr; itemPtr = oCItemContainer_GetSelectedItem(contLeft);
if (itemPtr)
{
var C_ITEM citm; citm = _^(itemPtr);
};
};
if (CanBuyItem(citm))
{
MEM_WriteByte(oCViewDialogTrade__OnTransferRight + 7, 106); // push
} else
{
MEM_WriteByte(oCViewDialogTrade__OnTransferRight + 7, 195); // retn
};
};
I assume that I'm right that for oCViewDialogTrade__OnTransferRight address I need +7 (oldInstr for oCViewDialogTrade__OnTransferRight is 7) and problem is with values. It seems that 106 and 195 isn't correct for
oCViewDialogTrade__OnTransferRight anymore. If that is, does someone knows correct values? Or am I totally wrong?
Geändert von Khantor (24.10.2021 um 18:50 Uhr)
-
Apprentice
Zitat von Khantor
I assume that I'm right that for oCViewDialogTrade__OnTransferRight address I need +7 (oldInstr for oCViewDialogTrade__OnTransferRight is 7) and problem is with values. It seems that 106 and 195 isn't correct for
oCViewDialogTrade__OnTransferRight anymore. If that is, does someone knows correct values? Or am I totally wrong?
Yea, I was right. If someone need this, correct value for "retn" is 247.
EDIT: OK, there is no correct value. 247 works, but if you use oCViewDialogTrade__OnTransferRight and oCViewDialogTrade__OnTransferLeft in the same time, block item to buy messing up blocking item to sell function.
Geändert von Khantor (01.11.2021 um 14:20 Uhr)
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
|
|