Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions doc/pandas_script_commands.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3382,4 +3382,47 @@ NPC名称:
否则由于动态生成魔物的影响, 必须在 BOSS 所在地图有玩家前往一次之后,
才能看到查询到那张地图的 BOSS 魔物信息.

--------------------------------------------------------------

*npchidecondition "<NPC名称>","<条件>";

让NPC根据条件决定是否对当前玩家不可见 [聽風]

NPC名称:
你可以指定 NPC 的名称, 或者用 strnpcinfo(0) 获取当前 NPC 的名称.

条件:
类似于 if 命令中的任何表达式(意思就是if里面怎么写,条件就怎么写)。

返回值:
该指令无论成功与否, 都不会有返回值

用法演示:
OnInit:
npchidecondition(strnpcinfo(0), "npcview == 1 && countitem(501) >= 1");
end;

解析:
NPC默认对所有玩家可见,指定NPC加上上述指令后,只要玩家 npcview 等于 1 且 红色药水 大于等于 1个
该NPC将对玩家不可见,如果在点击NPC对话后才达成需求条件,玩家需离开NPC可视范围再回来才会隐藏,
如果需要达成条件的同时对玩家隐藏,请使用cloakonnpc指令。
关于 cloakonnpc指令 ,cloakonnpc为临时隐藏NPC,玩家对目标NPC为暂时不可见,只要过图/重登,玩家依旧对该NPC可见

完整例子:

prontera,151,90,4 script Pandas系统测试 123,{
mes "你好啊";
mes "如果你身上有的话红色药水";
mes "我就不会见你!";
close2;
if ( countitem(501) ) {
npcview = 1;
cloakonnpc strnpcinfo(0),getcharid(0);
}
end;

OnInit:
npchidecondition(strnpcinfo(0), "npcview == 1 && countitem(501) >= 1");
end;
}
--------------------------------------------------------------
4 changes: 4 additions & 0 deletions src/config/pandas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2202,6 +2202,10 @@
//
// 更多详细用法请移步 doc/pandas_script_commands.txt 文件
#define Pandas_ScriptCommand_GetInventoryList

// 让NPC根据条件决定是否对当前玩家不可见 [聽風]
// 用法: npchidecondition "<NPC名称>","<条件>";
#define Pandas_ScriptCommand_NpcHideCondition
// PYHELP - SCRIPTCMD - INSERT POINT - <Section 1>
#endif // Pandas_ScriptCommands

Expand Down
5 changes: 5 additions & 0 deletions src/map/clif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5398,6 +5398,11 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){
bool option = false;
unsigned int option_val = 0;

#ifdef Pandas_ScriptCommand_NpcHideCondition
if ( bl->type == BL_NPC && !npc_hidecondition_check(sd, bl) )
return;
#endif // Pandas_ScriptCommand_NpcHideCondition

vd = status_get_viewdata(bl);
if (!vd || vd->class_ == JT_INVISIBLE)
return;
Expand Down
26 changes: 26 additions & 0 deletions src/map/npc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#include "pc.hpp"
#include "pet.hpp"
#include "script.hpp" // script_config
#ifdef Pandas_ScriptCommand_NpcHideCondition
#include "achievement.hpp"
#endif // Pandas_ScriptCommand_NpcHideCondition

#ifdef Pandas_NpcExpress_UNIT_KILL
#include "mapreg.hpp"
Expand Down Expand Up @@ -2596,6 +2599,12 @@ int npc_click(map_session_data* sd, struct npc_data* nd)
if(!nd) return 1;
if ((nd = npc_checknear(sd,&nd->bl)) == NULL)
return 1;

#ifdef Pandas_ScriptCommand_NpcHideCondition
if (!npc_hidecondition_check(sd, &nd->bl))
return 1;
#endif // Pandas_ScriptCommand_NpcHideCondition

//Hidden/Disabled npc.
if (nd->class_ < 0 || nd->sc.option&(OPTION_INVISIBLE|OPTION_HIDE))
return 1;
Expand Down Expand Up @@ -7781,3 +7790,20 @@ bool npc_change_title_event(map_session_data* sd, uint32 title_id, int mode) {
}
#endif // Pandas_Character_Title_Controller


#ifdef Pandas_ScriptCommand_NpcHideCondition
bool npc_hidecondition_check(map_session_data* sd, struct block_list* bl) {
struct npc_data* nd = ((TBL_NPC*)bl);

for (int i = 0; i < nd->HideConditionList.size(); i++) {
if (!nd || nd->HideConditionList.empty())
continue;
for (auto& data : nd->HideConditionList) {
if (achievement_check_condition(data->condition, sd))
return false;
}
}

return true;
}
#endif // Pandas_ScriptCommand_NpcHideCondition
21 changes: 21 additions & 0 deletions src/map/npc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,19 @@ struct s_questinfo {
}
};

#ifdef Pandas_ScriptCommand_NpcHideCondition
struct s_npchidecondition {
std::string variable;
struct script_code* condition;

~s_npchidecondition() {
if (this->condition != nullptr) {
script_free_code(this->condition);
}
}
};
#endif // Pandas_ScriptCommand_NpcHideCondition

#ifdef Pandas_Redeclaration_Struct_Event_Data
struct event_data {
struct npc_data* nd;
Expand Down Expand Up @@ -258,6 +271,11 @@ struct npc_data {
#ifdef Pandas_Struct_Unit_CommonData
struct s_unit_common_data ucd;
#endif // Pandas_Struct_Unit_CommonData

#ifdef Pandas_ScriptCommand_NpcHideCondition
std::vector<std::shared_ptr<s_npchidecondition>> HideConditionList;
#endif // Pandas_ScriptCommand_NpcHideCondition

};

struct eri;
Expand Down Expand Up @@ -2701,4 +2719,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c
bool npc_change_title_event(map_session_data* sd, uint32 title_id, int mode);
#endif // Pandas_Character_Title_Controller

#ifdef Pandas_ScriptCommand_NpcHideCondition
bool npc_hidecondition_check(map_session_data* sd, struct block_list* bl);
#endif // Pandas_ScriptCommand_NpcHideCondition
#endif /* NPC_HPP */
51 changes: 51 additions & 0 deletions src/map/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32913,6 +32913,54 @@ BUILDIN_FUNC(whodropitem) {
}
#endif // Pandas_ScriptCommand_WhoDropItem

#ifdef Pandas_ScriptCommand_NpcHideCondition
/* ===========================================================
* 指令: npchidecondition
* 描述: 让NPC根据条件决定是否对当前玩家不可见 [聽風]
* 用法: npchidecondition "<NPC名称>","<条件>";
* 返回: 无返回值
* 作者: 聽風
* -----------------------------------------------------------*/
BUILDIN_FUNC(npchidecondition) {
const char* npc_name = script_getstr(st, 2);

struct npc_data* nd = npc_name2id(npc_name);

if (!nd) {
ShowError("npchidecondition: 目标不是NPC.\n");
return SCRIPT_CMD_FAILURE;
}

struct script_code* script = nullptr;

if (script_hasdata(st, 3)) {
const char* str = script_getstr(st, 3);

if (str) {
std::string condition(str);

if (condition.find("achievement_condition") == std::string::npos)
condition = "achievement_condition( " + condition + " );";

script = parse_script(condition.c_str(), "npchideconditionparsing", 0, SCRIPT_IGNORE_EXTERNAL_BRACKETS);
if (!script) {
st->state = END;
return SCRIPT_CMD_FAILURE;
}
}
}

std::shared_ptr<s_npchidecondition> data = std::make_shared<s_npchidecondition>();

data->variable = npc_name;
data->condition = script;

nd->HideConditionList.push_back(data);

return SCRIPT_CMD_SUCCESS;
}
#endif // Pandas_ScriptCommand_NpcHideCondition

// PYHELP - SCRIPTCMD - INSERT POINT - <Section 2>

/// script command definitions
Expand Down Expand Up @@ -33900,6 +33948,9 @@ struct script_function buildin_func[] = {
#ifdef Pandas_ScriptCommand_WhoDropItem
BUILDIN_DEF(whodropitem,"v??"), // 查询指定道具会从哪些魔物身上掉落以及掉落的机率信息 [Sola丶小克]
#endif // Pandas_ScriptCommand_WhoDropItem
#ifdef Pandas_ScriptCommand_NpcHideCondition
BUILDIN_DEF(npchidecondition,"ss"), // 让NPC根据条件决定是否对当前玩家可见 [聽風]
#endif // Pandas_ScriptCommand_NpcHideCondition
// PYHELP - SCRIPTCMD - INSERT POINT - <Section 3>

#include "../custom/script_def.inc"
Expand Down