scummvm/engines/watchmaker/walk/walk.cpp
2024-09-20 23:28:32 +02:00

779 lines
23 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "watchmaker/walk/walk.h"
#include "watchmaker/types.h"
#include "watchmaker/t3d.h"
#include "watchmaker/globvar.h"
#include "watchmaker/3d/geometry.h"
#include "watchmaker/3d/t3d_body.h"
#include "watchmaker/walk/walkutil.h"
#include "watchmaker/windows_hacks.h"
#include "watchmaker/walk/act.h"
namespace Watchmaker {
// locals
/*
WALK60 0 225 0
WALKBACK 4 162 226
RUN80 5 92 385
GIRODX 4 63 473
GIROSX 4 63 533
aNULL 0 x3 0 0
aSTAND 1 x3 3 3
aWALK_START 1+ x3 4 4
aWALK_LOOP 14 x3 42 42
aWALK_END 75 x3 225 225
aBACK_START 1+ x3 4 226
aBACK_LOOP 12 x3 36 258
aBACK_END 54 x3 162 384
aRUN_START 1+ x4 5 385
aRUN_LOOP 7 x4 28 408
aRUN_END 23 x4 92 472
aROT_DX 21 x3 63 473
aROT_SX 21 x3 63 533
592
*/
int32 ActionStart[] = {0, 3, 4, 42, 225, 226, 258, 384, 385, 408, 472, 473, 533, 592 };
// N S WS WL WE BS BL BE RS, RL RE RD RS
int32 ActionLen[] = {1, 1, 38, 183, 1, 32, 126, 1, 23, 64, 1, 63, 63, 0};
/*-----------------16/10/96 11.07-------------------
Guarda e 2 pannelli sono nello stesso blocco
--------------------------------------------------*/
int FindAttachedPanel(int32 oc, int srcp, int destp) {
t3dCHARACTER *Act = Character[oc];
t3dWALK *w = &Act->Walk;
int curp;
int nearp;
int b;
// se almeno uno e' sul pavimento sul pavimento esci
if ((srcp < 0) || (destp < 0))
return (0);
// se sono uguali torna 1
if (srcp == destp)
return (1);
curp = srcp;
nearp = w->Panel[srcp].near1;
for (b = 0;; b++) {
// se sono attaccati torna 1
if (curp == destp)
return (1);
// se e' tornato al pannello di partenza torna 0
if ((srcp == curp) && (b))
return (0);
if (b > w->PanelNum)
return (0);
// se sono attaccati al vertice 1 prende il 2
if (w->Panel[nearp].near1 == curp) {
curp = nearp;
nearp = w->Panel[curp].near2;
} else {
curp = nearp;
nearp = w->Panel[curp].near1;
}
}
}
/*-----------------19/10/96 10.38-------------------
Fa uscire puto da pannello interno
--------------------------------------------------*/
void PointOut(int32 oc, t3dCAMERA *Camera) {
t3dCHARACTER *Act = Character[oc];
t3dWALK *w = &Act->Walk;
PointXZ p;
float inters;
float temp;
float nx, nz;
int b;
#define LARGEVAL 60.0 // 30 cm = 15 enlarge * 2
inters = 32000.0;
// se ho beccato il pavimento devo contare quante volte interseca
// i box larghi la retta omino pto
if (w->CurPanel < 0)
return;
nx = w->Panel[w->CurPanel].a.z - w->Panel[w->CurPanel].b.z;
nz = w->Panel[w->CurPanel].b.x - w->Panel[w->CurPanel].a.x;
temp = (t3dF32)sqrt(nx * nx + nz * nz);
nx /= temp;
nz /= temp;
// sposta il punto trovato sui pannelli larghi
for (b = 0; b < w->PanelNum; b++) {
// controlla solo pannelli esterni con stessi flags
// if( ( Panel[b].flags & 0x80000000 ) &&
// ( Panel[b].flags & (Panel[CurPanel].flags & 0x7FFFFFFF) ) )
{
// controlla pto 1
temp = DistF(w->Cur, w->Panel[b].a);
if (temp < inters) {
inters = temp;
w->CurPanel = b;
p = w->Panel[b].a;
}
// controlla pto 2
temp = DistF(w->Cur, w->Panel[b].b);
if (temp < inters) {
inters = temp;
w->CurPanel = b;
p = w->Panel[b].b;
}
// controlla intersezione con camera
PointResult res = IntersLineLine(w->Panel[b].a, w->Panel[b].b,
Camera->Source.x, Camera->Source.z,
w->Cur.x, w->Cur.z);
if (res.isValid) {
temp = DistF(w->Cur, res.result);
if (temp < inters) {
inters = temp;
w->CurPanel = b;
p = res.result;
}
}
// controlla intersezione con omino
res = IntersLineLine(w->Panel[b].a, w->Panel[b].b,
Act->Pos.x, Act->Pos.z,
w->Cur.x, w->Cur.z);
if (res.isValid) {
temp = DistF(w->Cur, res.result);
if (temp < inters) {
inters = temp;
w->CurPanel = b;
p = res.result;
}
}
// controlla intersezione con normale pannello
/* PointResult res = IntersLineLine( w->Panel[b].x1, w->Panel[b].z1,
w->Panel[b].x2, w->Panel[b].z2,
w->CurX+nx*LARGEVAL, w->CurZ+nz*LARGEVAL,
w->CurX-nx*LARGEVAL, w->CurZ-nz*LARGEVAL );
if (res.isValid)
{
temp = DistF( w->Cur, res.result );
if( temp < inters )
{
inters = temp;
w->CurPanel = b;
x = res.result.x;
z = res.result.z;
}
}
*/
}
}
w->Cur = p;
#undef LARGEVAL
}
/*-----------------15/10/96 14.23-------------------
Valuta lunghezza percorso
--------------------------------------------------*/
float EvalPath(int32 oc, int a, PointXZ dest, int nearp) {
t3dCHARACTER *Act = Character[oc];
t3dWALK *w = &Act->Walk;
float len;
PointXZ cur;
int b;
int curp;
b = 0;
len = 0.0;
curp = w->PathNode[a].curp;
cur = w->PathNode[a].pos;
for (;;) {
// se raggiunge il pto esce
if (curp == w->PathNode[a + 1].curp) {
len += DistF(cur, w->PathNode[a + 1].pos);
break;
}
// se e' tornato al pannello di partenza non trova starda
if ((curp == w->PathNode[a].curp) && (b)) {
len += 320000.0; // lunghezza assurda
break;
}
// altrimenti va fino al prossimo pannello
// se nearp e' attacato a curp col vertice 1
if (w->Panel[nearp].near1 == curp) {
// vai al vertice 2 la prossima volta
len += DistF(cur, dest);
cur = dest;
dest = w->Panel[nearp].b;
curp = nearp;
nearp = w->Panel[curp].near2;
} else {
// vai al vertice 1 la prossima volta
len += DistF(cur, dest);
cur = dest;
dest = w->Panel[nearp].a;
curp = nearp;
nearp = w->Panel[curp].near1;
}
b++;
}
return (len);
}
/*-----------------15/10/96 10.18-------------------
cerca percorso piu' corto aggirando ostacoli
--------------------------------------------------*/
void FindShortPath(int32 oc) {
t3dCHARACTER *Act = Character[oc];
t3dWALK *w = &Act->Walk;
t3dPATHNODE TempPath[T3D_MAX_PATHNODES];
int count = 0, inters;
float len1, len2;
PointXZ cur;
int curp, nearp, oldp;
PointXZ dest;
signed int a, b, c, fail = 0;
count = 0;
// aggiunge partenza
TempPath[count].pos.x = Act->Pos.x;
TempPath[count].pos.z = Act->Pos.z;
TempPath[count].dist = 0.0;
TempPath[count].oldp = w->OldPanel;
TempPath[count].curp = w->OldPanel;
count ++;
// per ogni ostacolo cerca di aggirarlo a destra e a sinistra
// poi guarda quello che e' piu' corto
for (a = 0; a < w->NumPathNodes - 1; a++) {
memcpy(&TempPath[count], &w->PathNode[a], sizeof(t3dPATHNODE));
count ++;
curp = w->PathNode[a].curp;
// se pannello sorgente e destinazione non sono sullo stesso blocco
if (!(FindAttachedPanel(oc, curp, w->PathNode[a + 1].curp)))
continue;
// aggira l'ostacolo partendo da near1
len1 = EvalPath(oc, a, w->Panel[curp].a, w->Panel[curp].near1) + DistF(w->PathNode[a].pos, w->Panel[curp].a);
// aggira l'ostacolo partendo da near2
len2 = EvalPath(oc, a, w->Panel[curp].b, w->Panel[curp].near2) + DistF(w->PathNode[a].pos,w->Panel[curp].b);
// guarda quale starda era piu' breve e se esiste una strada
if ((len1 < 320000.0) && (len2 < 320000.0)) {
if (len1 < len2) {
dest = w->Panel[curp].a;
nearp = w->Panel[curp].near1;
} else {
dest = w->Panel[curp].b;
nearp = w->Panel[curp].near2;
}
cur = w->PathNode[a].pos;
oldp = curp;
b = 0;
// salva percorso piu corto
for (;;) {
TempPath[count].pos = cur;
TempPath[count].oldp = oldp;
TempPath[count].curp = curp;
count ++;
// se raggiunge il pto esce
if (curp == w->PathNode[a + 1].curp) {
// attenzione: prima era
//memcpy( &TempPath[count], &PathNode[++a], sizeof( struct SPathNode ) );
memcpy(&TempPath[count], &w->PathNode[a + 1], sizeof(t3dPATHNODE));
count ++;
break;
}
// se e' tornato al pannello di partenza non trova starda
if ((curp == w->PathNode[a].curp) && (b)) {
fail = 1; // si ferma al vertice prima
break; // e non contiuma a camminare
}
// altrimenti va fino al prossimo pannello
// se nearp e' attacato a curp col vertice 1
if (w->Panel[nearp].near1 == curp) {
// vai al vertice 2 la prossima volta
cur = dest;
dest = w->Panel[nearp].b;
oldp = curp;
curp = nearp;
nearp = w->Panel[curp].near2;
} else {
// vai al vertice 1 la prossima volta
cur = dest;
dest = w->Panel[nearp].a;
oldp = curp;
curp = nearp;
nearp = w->Panel[curp].near1;
}
b++;
}
} else {
//DebugText("Fail: FindShortPath");
fail = 1;
}
if (fail) // se non riesce ad aggirare ostacolo si ferma
break;
}
// aggiunge arrivo
TempPath[count].pos = w->Cur;
TempPath[count].dist = 0.0;
TempPath[count].oldp = w->CurPanel;
TempPath[count].curp = w->CurPanel;
count ++;
for (b = 0; b < count; b++)
DebugLogFile("FSP %d: %f %f | %d %d", b, TempPath[b].pos.x, TempPath[b].pos.z, TempPath[b].oldp, TempPath[b].curp);
// dopo che ha aggirato tutti gli ostacoli ottimizza
// memcpy( w->PathNode, TempPath, sizeof( struct SPathNode )*count );
// w->NumPathNodes = count;
// return ;
w->NumPathNodes = 0;
for (a = 0; a < count; a++) {
//printf("N:%d | ",a);
if (w->NumPathNodes > (T3D_MAX_PATHNODES - 2))
w->NumPathNodes = (T3D_MAX_PATHNODES - 2);
// prima leva tutti i nodi attaccati
for (b = (count - 1); b >= a; b--)
if (DistF(TempPath[b].pos, TempPath[a].pos) < EPSILON)
break;
DebugLogFile("Da %d passo a %d\n", a, b);
a = b;
memcpy(&w->PathNode[w->NumPathNodes], &TempPath[a], sizeof(t3dPATHNODE));
w->NumPathNodes ++;
for (b = (count - 1); b > a + 1; b--) {
inters = 0;
for (c = 0; c < w->PanelNum; c++) {
// non deve intersecare pannello stretto mai
// if( !( w->Panel[c].flags & 0x80000000 ) )
{
PointResult res = IntersLineLine(w->Panel[c].backA, w->Panel[c].backB,
TempPath[a].pos, TempPath[b].pos);
if (res.isValid)
inters ++;
res = IntersLineLine(w->Panel[c].a, w->Panel[c].backA,
TempPath[a].pos, TempPath[b].pos);
if (res.isValid) {
len2 = DistF(res.result, TempPath[a].pos);
len1 = DistF(res.result, TempPath[b].pos);
// interseca in un pto distante da partenza e arrivo
if ((len1 > EPSILON) && (len2 > EPSILON))
inters ++;
}
res = IntersLineLine(w->Panel[c].b, w->Panel[c].backB,
TempPath[a].pos, TempPath[b].pos);
if (res.isValid) {
len2 = DistF(res.result, TempPath[a].pos);
len1 = DistF(res.result, TempPath[b].pos);
// interseca in un pto distante da partenza e arrivo
if ((len1 > EPSILON) && (len2 > EPSILON))
inters ++;
}
if (inters)
break;
}
}
// se da a posso raggiungere b direttamente
if (!inters) {
curp = w->PathNode[w->NumPathNodes - 1].curp;
oldp = TempPath[b].oldp;
for (c = a; c <= b; c++)
if ((TempPath[c].oldp == curp) && (TempPath[c].curp == oldp))
break;
// se non erano collegati signica che e' passato per il pavimento
if (c > b) {
DebugLogFile("Arr %d %d Part %d %d | %d", b, TempPath[b].oldp, a, w->PathNode[w->NumPathNodes - 1].curp, w->NumPathNodes - 1);
w->PathNode[w->NumPathNodes - 1].curp = -1; // partenza
TempPath[b].oldp = -1; // arrivo
}
a = b - 1;
break;
}
}
}
for (b = 0; b < w->NumPathNodes; b++)
DebugLogFile("SSP %d: %f %f | %d %d", b, w->PathNode[b].pos.x, w->PathNode[b].pos.z, w->PathNode[b].oldp, w->PathNode[b].curp);
}
/* -----------------04/02/98 15.48-------------------
* Crea percorso
* --------------------------------------------------*/
void FindPath(int32 oc, t3dCAMERA *Camera) {
t3dCHARACTER *Act = Character[oc];
t3dWALK *w = &Act->Walk;
int inters, check;
float dist;
int b;
w->NumPathNodes = 0;
w->CurrentStep = 0;
w->NumSteps = 0;
// FIXME: condition never happen!
//if( !w->PathNode ) return;
check = 0;
inters = 0;
w->NumPathNodes = 0;
w->OldPanel = w->CurPanel;
if (FloorHit)
w->CurPanel = -1;
/* else
w->CurPanel = 1;
*/
PointOut(oc, Camera);
w->Look = w->Cur;
// se hai cliccato dietro il pannello di partenza o dell'angolo non puo' camminare
if ((w->CurPanel < 0) && (w->OldPanel >= 0) &&
// dietro il pannello di partenza
((PointInside(oc, b = w->OldPanel, w->Cur)) ||
// dietro il pannello angolo1
((DistF(w->Panel[w->OldPanel].a.x, w->Panel[w->OldPanel].a.z, Act->Pos.x, Act->Pos.z) < EPSILON) &&
(PointInside(oc, b = w->Panel[w->OldPanel].near1, w->Cur))) ||
// dietro il pannello angolo2
((DistF(w->Panel[w->OldPanel].b.x, w->Panel[w->OldPanel].b.z, Act->Pos.x, Act->Pos.z) < EPSILON) &&
(PointInside(oc, b = w->Panel[w->OldPanel].near2, w->Cur))))) {
w->Cur.x = Act->Pos.x;
w->Cur.z = Act->Pos.z;
w->CurPanel = b;
w->NumPathNodes = 0;
check |= CLICKINTO;
w->Check = check;
return ;
}
DebugLogFile("W: CP %d OP %d | %f %f | %f %f", w->CurPanel, w->OldPanel, Act->Pos.x, Act->Pos.z, w->Cur.x, w->Cur.z);
dist = DistF(Act->Pos.x, Act->Pos.z, w->Cur.x, w->Cur.z);
// if( dist < EPSILON )
// return ;
for (b = 0; b < w->PanelNum; b++) {
PointResult res = IntersLineLine(w->Panel[b].a, w->Panel[b].b,
Act->Pos.x, Act->Pos.z,
w->Cur.x, w->Cur.z);
if (res.isValid) {
inters ++;
DebugLogFile("Inters %d: %f %f %f %f", b, w->Panel[b].a.x, w->Panel[b].a.z, w->Panel[b].b.x, w->Panel[b].b.z);
w->PathNode[w->NumPathNodes].pos = res.result;
w->PathNode[w->NumPathNodes].dist = DistF(Act->Pos.x, Act->Pos.z, res.result.x, res.result.z);
w->PathNode[w->NumPathNodes].oldp = b;
w->PathNode[w->NumPathNodes].curp = b;
w->NumPathNodes ++;
// ANGOLI - leva intersezioni in angoli
if ((w->OldPanel >= 0) && ((b == w->Panel[w->OldPanel].near1) || (b == w->Panel[w->OldPanel].near2))) {
// altrimenti se e' vicino al pannello di partenza
if ((w->PathNode[w->NumPathNodes - 1].dist < EPSILON) &&
(b != w->OldPanel) && (b != w->CurPanel)) {
// e la distanza e' molto piccola leva l'intersezione
inters --;
w->NumPathNodes --;
check |= OLDANGLESKIP;
// se ho cliccato dentro il pannello vicino
if ((w->CurPanel < 0) && (PointInside(oc, b, w->Cur))) {
w->Cur.x = Act->Pos.x;
w->Cur.z = Act->Pos.z;
w->CurPanel = b;
w->NumPathNodes = 0;
check |= CLICKINTO;
w->Check = check;
return ;
}
}
} else if ((w->CurPanel >= 0) && ((b == w->Panel[w->CurPanel].near1) || (b == w->Panel[w->CurPanel].near2))) {
// altrimenti se e' vicino al pannello di arrivo
if ((fabs(w->PathNode[w->NumPathNodes - 1].dist - dist) < EPSILON) &&
(b != w->OldPanel) && (b != w->CurPanel)) {
// e la distanza e' molto piccola leva l'intersezione
inters --;
w->NumPathNodes --;
check |= CURANGLESKIP;
}
}
}
// aggiunge sempre nodo partenza e arrivo solo se su un pannelli
else if (b == w->OldPanel) {
inters ++;
w->PathNode[w->NumPathNodes].pos.x = Act->Pos.x;
w->PathNode[w->NumPathNodes].pos.z = Act->Pos.z;
w->PathNode[w->NumPathNodes].dist = 0.0;
w->PathNode[w->NumPathNodes].oldp = w->OldPanel;
w->PathNode[w->NumPathNodes].curp = w->OldPanel;
w->NumPathNodes ++;
check |= NOOLDINTERS;
} else if (b == w->CurPanel) {
inters ++;
w->PathNode[w->NumPathNodes].pos = w->Cur;
w->PathNode[w->NumPathNodes].dist = dist;
w->PathNode[w->NumPathNodes].oldp = w->CurPanel;
w->PathNode[w->NumPathNodes].curp = w->CurPanel;
w->NumPathNodes ++;
check |= NOCURINTERS;
}
}
// il percorso e' definito da:
// start Act.px, Act.pz
// NumPathNodes PathNode
// end CurX, CurZ
// se scontra contro qualche pannello
if (inters) {
SortPath(oc);
// se dispari e vado nel pavimento ma non sono partito da pannello
// se vado nel pavimento e ultimi due nodi non sono su stesso blocco
// se all'esterno dell'ultimo pannello sposta ultimo nodo
if (w->NumPathNodes > 1)
DebugLogFile("I %d | CP %d | OP %d | FA %d (%d %d) | PI %d (%d)", inters, w->CurPanel, w->OldPanel,
FindAttachedPanel(oc, w->PathNode[w->NumPathNodes - 2].curp, w->PathNode[w->NumPathNodes - 1].curp), w->PathNode[w->NumPathNodes - 2].curp, w->PathNode[w->NumPathNodes - 1].curp,
PointInside(oc, w->PathNode[w->NumPathNodes - 1].curp, w->Cur), w->PathNode[w->NumPathNodes - 1].curp);
if (((inters & 1) && (w->CurPanel < 0) && (w->OldPanel < 0)) ||
((w->CurPanel < 0) && (w->NumPathNodes >= 1) && (PointInside(oc, w->PathNode[w->NumPathNodes - 1].curp, w->Cur))) ||
(((inters - 1) & 1) && (w->CurPanel < 0) && (w->NumPathNodes >= 2) &&
(!(FindAttachedPanel(oc, w->PathNode[w->NumPathNodes - 2].curp, w->PathNode[w->NumPathNodes - 1].curp)) ||
(PointInside(oc, w->PathNode[w->NumPathNodes - 1].curp, w->Cur))))) {
w->CurPanel = w->PathNode[w->NumPathNodes - 1].curp;
PointOut(oc, Camera); // tira fuori il pto trovato
w->PathNode[w->NumPathNodes].pos = w->Cur;
w->PathNode[w->NumPathNodes].oldp = w->CurPanel;
w->PathNode[w->NumPathNodes].curp = w->CurPanel;
UpdateLook(oc);
w->NumPathNodes ++;
check |= POINTOUT1;
DebugLogFile("PO %d %d %f", w->NumPathNodes, w->CurPanel, DistF(Act->Pos.x, Act->Pos.z, w->Cur.x, w->Cur.z));
// if ( DistF( Act->Pos.x, Act->Pos.z, w->CurX, w->CurZ ) < EPSILON )
// check |= CLICKINTO;
}
// se arrivo su pavimento
if (w->CurPanel < 0) {
inters = 0;
// conto intersezioni con pannelli stretti
// e con unione pannelli larghi con pannelli stretti
for (b = 0; b < w->PanelNum; b++) {
PointResult res;
res = IntersLineLine(w->Panel[b].a, w->Panel[b].b,
w->PathNode[w->NumPathNodes - 1].pos, w->Cur);
if (res.isValid)
if ((DistF(res.result, w->PathNode[w->NumPathNodes - 1].pos) > EPSILON) &&
(DistF(res.result, w->Cur) > EPSILON))
inters ++;
res = IntersLineLine(w->Panel[b].a, w->Panel[b].backA,
w->PathNode[w->NumPathNodes - 1].pos, w->Cur);
if (res.isValid)
if ((DistF(res.result, w->PathNode[w->NumPathNodes - 1].pos) > EPSILON) &&
(DistF(res.result, w->Cur) > EPSILON))
inters ++;
res = IntersLineLine(w->Panel[b].b, w->Panel[b].backB,
w->PathNode[w->NumPathNodes - 1].pos, w->Cur);
if (res.isValid)
if ((DistF(res.result, w->PathNode[w->NumPathNodes - 1].pos) > EPSILON) &&
(DistF(res.result, w->Cur) > EPSILON))
inters ++;
if (inters)
break;
}
// se nell'ultimo tratto c'e un ostacolo leva primo nodo
if (inters) {
w->CurPanel = w->PathNode[w->NumPathNodes - 1].curp;
PointOut(oc, Camera); // tira fuori il pto trovato
w->PathNode[w->NumPathNodes].pos = w->Cur;
w->PathNode[w->NumPathNodes].oldp = w->CurPanel;
w->PathNode[w->NumPathNodes].curp = w->CurPanel;
UpdateLook(oc);
w->NumPathNodes ++;
check |= POINTOUT2;
}
}
DebugLogFile("CP: %d || OP: %d || %f %f || I: %d || C: %d || NPN: %d", w->CurPanel, w->OldPanel, w->Cur.x, w->Cur.z, inters, check, w->NumPathNodes);
//DebugText("CP: %d || OP: %d || I: %d || C: %d || PI: %d || NPN: %d", CurPanel, OldPanel, inters, check, PointInside( OldPanel, CurX, CurZ ), NumPathNodes );
w->PathNode[w->NumPathNodes].pos = w->Cur;
w->PathNode[w->NumPathNodes].dist = DistF(Act->Pos.x, Act->Pos.z, w->Cur.x, w->Cur.z);
w->PathNode[w->NumPathNodes].oldp = w->CurPanel;
w->PathNode[w->NumPathNodes].curp = w->CurPanel;
w->NumPathNodes ++;
for (b = 0; b < w->NumPathNodes; b++)
DebugLogFile("FP %d: %f %f | %d %d", b, w->PathNode[b].pos.x, w->PathNode[b].pos.z, w->PathNode[b].oldp, w->PathNode[b].curp);
FindShortPath(oc);
// DisplayPath();
} else { // altrimenti starda diretta
DebugLogFile("NOI CP: %d || OP: %d || I: %d || C: %d || NPN: %d", w->CurPanel, w->OldPanel, inters, check, w->NumPathNodes);
//DebugText("NOI CP: %d || OP: %d || I: %d || C: %d || PI: %d || NPN: %d", CurPanel, OldPanel, inters, check, PointInside( OldPanel, CurX, CurZ ), NumPathNodes );
w->PathNode[w->NumPathNodes].pos.x = Act->Pos.x;
w->PathNode[w->NumPathNodes].pos.z = Act->Pos.z;
w->PathNode[w->NumPathNodes].dist = 0.0;
w->PathNode[w->NumPathNodes].oldp = w->OldPanel;
w->PathNode[w->NumPathNodes].curp = w->OldPanel;
w->NumPathNodes ++;
w->PathNode[w->NumPathNodes].pos = w->Cur;
w->PathNode[w->NumPathNodes].dist = DistF(Act->Pos.x, Act->Pos.z, w->Cur.x, w->Cur.z);
w->PathNode[w->NumPathNodes].oldp = w->CurPanel;
w->PathNode[w->NumPathNodes].curp = w->CurPanel;
w->NumPathNodes ++;
}
w->Check = check;
DebugLogFile("End Walk %f %f %d | %f %f %d", Act->Pos.x, Act->Pos.z, w->OldPanel, w->Cur.x, w->Cur.z, w->CurPanel);
}
/* -----------------12/02/99 11.07-------------------
* ForceAnimInBounds
* --------------------------------------------------*/
void ForceAnimInBounds(int32 oc) {
t3dCHARACTER *Act = Character[oc];
t3dWALK *w = &Act->Walk;
t3dV3F *Trasl;
int inters, nf;
float dist;
int a, b;
if (!Act || !w) return ;
nf = Act->Mesh->Anim.NumFrames;
Trasl = Act->Mesh->Anim.BoneTable[0].Trasl;
if (!Trasl) return ;
inters = 0;
dist = DistF(Trasl[0].x, Trasl[0].z, Trasl[nf - 1].x, Trasl[nf - 1].z);
if (dist < EPSILON) return ; // Se non si muove esce
for (a = 1; a < nf; a++) {
for (b = 0; b < w->PanelNum; b++) {
// Se all'ultimo frame finirei dentro un pannello aggiorna CurPanel
if ((a == (nf - 1)) && (PointInside(oc, b, Trasl[a].x, Trasl[a].z))) {
w->OldPanel = w->CurPanel;
w->CurPanel = b;
DebugLogFile("Aggiorno CurPanel %d", b);
}
// Se un punto interseca pannello slida
PointResult res = IntersLineLine(w->Panel[b].a, w->Panel[b].b,
Trasl[0].x, Trasl[0].z,
Trasl[a].x, Trasl[a].z);
if (res.isValid) {
inters ++;
Trasl[a].x = res.result.x;
Trasl[a].z = res.result.z;
DebugLogFile("%d: entrerebbe in %d", a, b);
}
}
}
(void)inters;
}
} // End of namespace Watchmaker