不想贴成品了,说一下思路吧:
1. 游戏限制法术和类法术能力,对于指定目标释放是有条件的,那就是目标必须是施法者目力所及,并且没有遮挡。这就决定了如果有一个法术脚本要对不能直视的目标起作用,就不能通过GetSpellTargetLocation来得到这个目标,因为这样以来,系统会判定目标不可见,而直接终止法术施放。
2. 对于穿墙术来说,其实脚本并不需要我来告诉它穿过墙之后的具体位置,过墙位置是脚本可以自动探测的(下文可以看到,其实是用了一些trick,说试探或许更准确)。那么法术本身的2DA设置其实配成TARGET_SELF就足够了。
3. 那么过墙位置应该如何得到?首先,脚本需要判断一下,PC面前是否有一面墙,这可以通过 LineOfSightVector() 得到。但是Toolset没有提供接口得到某个位置是否是生物可以进入的,应该怎么办呢?
4. 既然前面有了一堵墙,那么就意味着PC朝向的若干距离内是生物不可进入的。这就意味着我可以通过放置一些“替身”,去尝试墙的后面是否有位置可以传送。
5. 一旦被试出某个位置可以放置生物(同时判断一下距离,取最近),过墙位置也就可以确定。将该位置转换为Location,传给ActionJumpToLocation完成穿墙。
代码如下:
#include "x2_inc_spellhook"
int GetIsFacingWall(object oObject)
{
vector vPosition = GetPosition(oObject);
float fFacing = GetFacing(oObject);
vector vChangedPosition;
int i;
for(i = 1; i < 3; i++) //前面3米内是否视线无法穿透
{
vChangedPosition = GetChangedPosition(vPosition, IntToFloat(i), fFacing);
if(!LineOfSightVector(vPosition, vChangedPosition))
{
return TRUE;
}
}
return FALSE;
}
void main()
{
object oCaster = OBJECT_SELF;
if(!GetIsObjectValid(oCaster))
{
SpeakString("Invalid caster");
return;
}
if(!GetIsFacingWall(oCaster))
{
SpeakString("No wall detected");
return;
}
object oArea = GetArea(oCaster);
vector vPosition = GetPosition(oCaster);
SpeakString(VectorToString(vPosition));
float fFacing = GetFacing(oCaster);
vector vChangedPosition;
object oTarget;
vector vTarget;
int i;
int nGo = FALSE;
for(i = 1; i < 25; i+=1)
{
vChangedPosition = GetChangedPosition(vPosition, IntToFloat(i), fFacing);
oTarget = CreateObject(OBJECT_TYPE_CREATURE, "NW_DWARFMERC001", Location(oArea, vChangedPosition, fFacing)); //放置替身
vTarget = GetPosition(oTarget); // 得到替身实际位置
AssignCommand(oTarget, SetIsDestroyable(TRUE, FALSE));
DestroyObject(oTarget); // 消除替身
if(!LineOfSightVector(vPosition, vTarget)) // 如果替身位于墙后
{
nGo = TRUE;
break;
}
}
if(!nGo)
{
SpeakString("Unpiercable wall");
return;
}
location lTarget = Location(oArea, vTarget, fFacing);
ActionJumpToLocation(lTarget); // 完成传送
}
1. 游戏限制法术和类法术能力,对于指定目标释放是有条件的,那就是目标必须是施法者目力所及,并且没有遮挡。这就决定了如果有一个法术脚本要对不能直视的目标起作用,就不能通过GetSpellTargetLocation来得到这个目标,因为这样以来,系统会判定目标不可见,而直接终止法术施放。
2. 对于穿墙术来说,其实脚本并不需要我来告诉它穿过墙之后的具体位置,过墙位置是脚本可以自动探测的(下文可以看到,其实是用了一些trick,说试探或许更准确)。那么法术本身的2DA设置其实配成TARGET_SELF就足够了。
3. 那么过墙位置应该如何得到?首先,脚本需要判断一下,PC面前是否有一面墙,这可以通过 LineOfSightVector() 得到。但是Toolset没有提供接口得到某个位置是否是生物可以进入的,应该怎么办呢?
4. 既然前面有了一堵墙,那么就意味着PC朝向的若干距离内是生物不可进入的。这就意味着我可以通过放置一些“替身”,去尝试墙的后面是否有位置可以传送。
5. 一旦被试出某个位置可以放置生物(同时判断一下距离,取最近),过墙位置也就可以确定。将该位置转换为Location,传给ActionJumpToLocation完成穿墙。
代码如下:
#include "x2_inc_spellhook"
int GetIsFacingWall(object oObject)
{
vector vPosition = GetPosition(oObject);
float fFacing = GetFacing(oObject);
vector vChangedPosition;
int i;
for(i = 1; i < 3; i++) //前面3米内是否视线无法穿透
{
vChangedPosition = GetChangedPosition(vPosition, IntToFloat(i), fFacing);
if(!LineOfSightVector(vPosition, vChangedPosition))
{
return TRUE;
}
}
return FALSE;
}
void main()
{
object oCaster = OBJECT_SELF;
if(!GetIsObjectValid(oCaster))
{
SpeakString("Invalid caster");
return;
}
if(!GetIsFacingWall(oCaster))
{
SpeakString("No wall detected");
return;
}
object oArea = GetArea(oCaster);
vector vPosition = GetPosition(oCaster);
SpeakString(VectorToString(vPosition));
float fFacing = GetFacing(oCaster);
vector vChangedPosition;
object oTarget;
vector vTarget;
int i;
int nGo = FALSE;
for(i = 1; i < 25; i+=1)
{
vChangedPosition = GetChangedPosition(vPosition, IntToFloat(i), fFacing);
oTarget = CreateObject(OBJECT_TYPE_CREATURE, "NW_DWARFMERC001", Location(oArea, vChangedPosition, fFacing)); //放置替身
vTarget = GetPosition(oTarget); // 得到替身实际位置
AssignCommand(oTarget, SetIsDestroyable(TRUE, FALSE));
DestroyObject(oTarget); // 消除替身
if(!LineOfSightVector(vPosition, vTarget)) // 如果替身位于墙后
{
nGo = TRUE;
break;
}
}
if(!nGo)
{
SpeakString("Unpiercable wall");
return;
}
location lTarget = Location(oArea, vTarget, fFacing);
ActionJumpToLocation(lTarget); // 完成传送
}