Skip to content

Instantly share code, notes, and snippets.

@zapu
Created May 13, 2016 09:01
Show Gist options
  • Save zapu/c9a7a4660b23b26e78f1fdb44bea5645 to your computer and use it in GitHub Desktop.
Save zapu/c9a7a4660b23b26e78f1fdb44bea5645 to your computer and use it in GitHub Desktop.
Ultima 6 Online
#include "define_both.h" /* luteijn: won't really be included again, but helps with auto-completion of variable names. */
if (NEThost){ //host
//U6O_ERRORTAG
btime2+=et/150.0f; //non-rolled over btime!
x=btime2/24;
btime=btime2-(float)x*24.0f;
x%=7; bday=x+1;
if (lastsecond==-1) lastsecond=ett; x=ett; //detect frame rate
if (x!=lastsecond){
lastsecond=x; framerate=framecount; framecount=0;
}
framecount++;
//Adjust economy values
for (i=0;i<=1023;i++){ for (i2=0;i2<=3;i2++){
if (economy_setup[i][i2]==TRUE){
if (economy_change[i][i2]){
f2=abs(economy_change[i][i2]); f=3600.0f/f2;
//f is how often it should occur without the exponential factor
f3=((float)economy_value[i][i2])/((float)economy_limit[i][i2]);//0-1
f3*=2.0f;//0-2
f3+=1.0f;//1-3
//f3 is a multiplier to make it take 3 times as long to increase as value reaches limit
f*=f3;
if (int((ett/f))!=int((ett/f)-(et/f))){
if (economy_change[i][i2]>0) economy_value[i][i2]++;
if (economy_change[i][i2]<0) economy_value[i][i2]--;
if (economy_value[i][i2]<0) economy_value[i][i2]=0;
if (economy_value[i][i2]>economy_limit[i][i2]) economy_value[i][i2]=economy_limit[i][i2];
}//f
}//economy_change
}//economy_setup==TRUE
}}//i,i2
//deduct house payments from housesav
f=300.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
housesav[0].flags+=5;
if (housesav[0].flags>=1440){
housesav[0].flags=0;
for (i=1;i<=255;i++){
if (housesav[i].flags&1){ //currently occupied
x=housesav[i].gold-housecost[i];
if (x<=0) x=0;
housesav[i].gold=x;
if (housesav[i].gold==0){
for (x2=0;x2<=playerlist_last;x2++){ if (playerlist[x2]){ //if (playerlist[x2]->net!=INVALID_NET){
if (playerlist[x2]->GNPCflags[28]==i) goto skipevict; //can't evict online player
//}
}}//x2,...
//evict owner
//MessageBox(NULL,"HOUSESTORAGECHECK: EVICT","Ultima 6 Online",MB_OK);
housesav[i].flags--; //remove house occupied flag
housesav_update();
}//gold==0
skipevict:;
}
}//i
}//housesav[0].flags>=1440
housesav_update();
}//f
/* hireling respawn*/
for (i=0;i<=HIRELINGS_MAX -1;i++){
hirl_wait[i]-=et;
if (hirl_wait[i]<=0){
if (hirl_obj[i]) {
hirl_obj[i]->info|=112;
tnpc=(npc*)hirl_obj[i]->more;
hirl_obj[i]=0;
addhireling(i,tnpc->schedule);
}
else {
addhireling(i,0);
}
}
}
//doorclose: relock door after waiting for 2 hours
for (i=0;i<=doorclose_last;i++){
if (doorclose_wait[i]>=1.0f){
doorclose_wait[i]+=et;
if (doorclose_wait[i]>=12288.0f){
doorclose_wait[i]=0;
doorclose_obj[i]->type=doorclose_oldtype[i]; OBJcheckflags(doorclose_obj[i]->x,doorclose_obj[i]->y);
if (doorclose_obj2[i]){
doorclose_obj2[i]->type=doorclose_oldtype2[i]; OBJcheckflags(doorclose_obj2[i]->x,doorclose_obj2[i]->y);
}//doorclose_obj2[i]
}//wait>=8192.0f
}//wait>=1.0f
}//i
//leverchange: revert lever position after waiting for 2 hours
for (i=0;i<=leverchange_last;i++){
if (leverchange_wait[i]>=1.0f){
leverchange_wait[i]+=et;
if (leverchange_wait[i]>=12288.0f){
leverchange_wait[i]=0;
if (leverchange_obj[i]->type!=leverchange_oldtype[i]){
use_basic_toggle(NULL,leverchange_obj[i]);
}
}//wait>=8192.0f
}//wait>=1.0f
}//i
ouln=-1; //object update/active list num
//add fixed objects to update
if (f_ouln!=-1){
for (i=0;i<=f_ouln;i++){
myobj=f_oul[i];
if (myobj->x||myobj->y){
ouln++;
oul[ouln]=f_oul[i];
oul[ouln]->info|=32768;
}//x&y not null
}
}
/*
for (i=0;i<=15;i++){
if (stolenitemwarning[i]){
stolenitemwarning_wait[i]-=et;
if (stolenitemwarning_wait[i]<=0.0f) stolenitemwarning[i]=NULL;
}//stolenitemwarning[i]
}//i
*/
//wind: change direction
windnew=0;
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (rnd*32.0f<1.0f){
windnew=1;
x=rnd*3; x--; windx=x;
x=rnd*3; x--; windy=x;
}
}
//recalculate moon phase!
moonphase=255; //NULL moon phase
f5=32;
f=btime2*1.125f+3.0f;
x=f/24; f-=(float)x*24.0f;
if ((f>5)&&(f<20)){
if (f>=12.0f) f3=-(f-12.0f); else f3=12.0f-f;
if (f>=12.0f) f5=f-12.0f; else f5=12.0f-f; //NEW
f3/=1.125f;
f2=btime+f3;
f4=f; f=12.0f;
if (f2>=24.0f) f2-=24.0f;
if (f2<0.0f) f2+=24.0f;
if (f2>=f) f2=f2-f; else f2=f2+(24.0f-f);
f2+=1.5f; if (f2>=24.0f) f2-=24.0f;
moonphase=f2/3.0f; //NEW
}
f=btime2*1.1875f+5.0f;
x=f/24; f-=(float)x*24.0f;
if ((f>5)&&(f<20)){
if (f>=12.0f) f3=-(f-12.0f); else f3=12.0f-f;
if (f>=12.0f) f6=f-12.0f; else f6=12.0f-f; //NEW
if (f6<f5){
f3/=1.1875f;
f2=btime+f3;
f4=f; f=12.0f;
if (f2>=24.0f) f2-=24.0f;
if (f2<0.0f) f2+=24.0f;
if (f2>=f) f2=f2-f; else f2=f2+(24.0f-f);
f2+=1.5f; if (f2>=24.0f) f2-=24.0f;
moonphase=f2/3.0f; //NEW
}//f6<f5
}
if (moonphase!=255){
//check moongates!
if (showmoongates==0){
//object *moongate[8][2];
//unsigned char showmoongates=0;
//unsigned short moongatex[8],moongatey[8];
for (i=0;i<=7;i++){
OBJadd(moongatex[i],moongatey[i],moongate[i][0]);
OBJadd(moongatex[i]-1,moongatey[i],moongate[i][1]);
}
showmoongates=1;
}
}else{ //255
if (showmoongates){
for (i=0;i<=7;i++){
OBJremove(moongate[i][0]);
OBJremove(moongate[i][1]);
}
showmoongates=0;
}
}//showmoongates
stormcloak_last=-1;
sfbufferwait+=et;
f=1.0f/8.0f;
if (sfbufferwait>=f){
sfbufferwait=0.0f;
sfbuffersend=1;
}
wizardeyesi=0;
for (tpl=0;tpl<=playerlist_last;tpl++){ if (playerlist[tpl]){ if (playerlist[tpl]->net){
tplayer=playerlist[tpl];
if (tplayer->wizardeyetimeleft){
wizardeyesi++;
wizardeyesx[wizardeyesi]=tplayer->wizardeyex;
wizardeyesy[wizardeyesi]=tplayer->wizardeyey;
}
}}}
for (tpl=0;tpl<=playerlist_last;tpl++){ //create and send UPDATE message
if (playerlist[tpl]){ //current player
if (playerlist[tpl]->net!=NULL){ //net connection available
tplayer=playerlist[tpl];
tplayer->online+=et;
/*
// luteijn: keep client in check, but this is too often?
// luteijn: it is, so now only sending it when saving.
//send time
txtset(t2,"?"); t2->d2[0]=32;
txtset(t3,"12345678"); t3->dd[0]=btime2;
txtadd(t2,t3);
NET_send(NETplayer,tplayer->net,t2);
*/
//doorclose: set/reset wait timer for door if player is near
if (myobj=tplayer->party[0]){
for (i=0;i<=doorclose_last;i++){
x=abs(doorclose_obj[i]->x-myobj->x); y=abs(doorclose_obj[i]->y-myobj->y);
if ((x<=16)&&(y<=12)){
doorclose_wait[i]=1.0f;
}//<=8
}//i
}//->party[0]
//leverchange: set/reset wait timer if player is near lever OR portcullis
if (myobj=tplayer->party[0]){
for (i=0;i<=leverchange_last;i++){
x=abs(leverchange_obj[i]->x-myobj->x); y=abs(leverchange_obj[i]->y-myobj->y);
if ((x<=16)&&(y<=12)){
leverchange_wait[i]=1.0f;
}//<=8
myobj2=(object*)leverchange_obj[i]->more;
leverchange0:
if (myobj2){
x=abs(myobj2->x-myobj->x); y=abs(myobj2->y-myobj->y);
if ((x<=16)&&(y<=12)){
leverchange_wait[i]=1.0f;
}//<=8
myobj2=(object*)myobj2->next;
goto leverchange0;
}
}//i
}//->party[0]
//orb
// luteijn: this updates the orb destinations a player has visited.
// visited means he was 8 or less squares from the spot.
//GNPCflags[22]: bitvector for available orb destinations
if (myobj=tplayer->party[0]){
x2=1;
for (y=0;y<=4;y++){ for (x=0;x<=4;x++){
x3=abs(myobj->x-orbx[x][y]); y3=abs(myobj->y-orby[x][y]);
if ((x3<=8)&&(y3<=8)){
tplayer->GNPCflags[22]|=x2;
}
x2=x2<<1;
}}//x,y
}//party[0]
if (tplayer->guardianstatuewait){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tplayer->guardianstatuewait--;
}
}
tplayer->wizardeyetimeleft-=et; if (tplayer->wizardeyetimeleft<0.0f) tplayer->wizardeyetimeleft=0.0f;
tplayer->wizardeyemovewait-=et; if (tplayer->wizardeyemovewait<0.0f) tplayer->wizardeyemovewait=0.0f;
tplayer->speaking-=et; if (tplayer->speaking<0.0f) tplayer->speaking=0.0f;
if (tplayer->rest){
tplayer->rest--;
if (tplayer->rest==16){
txtset(t,"??"); t->d2[0]=250; t->d2[1]=0; NET_send(NETplayer,tplayer->net,t);
}//rest==16
if (tplayer->rest==0){
tplayer->GNPCflags[253]|=(1+2);
}//rest==0
}//rest
//check trap indexes
for (i=0;i<=7;i++){
if (myobj=tplayer->party[i]){
if ((myobj->x!=tplayer->trapx[i])||(myobj->y!=tplayer->trapy[i])) {tplayer->trapx[i]=0; tplayer->trapy[i]=0;}
}
}
//add storm cloak fields
for (i=0;i<=7;i++){
if (myobj=tplayer->party[i]){
if (myobj->x){ //not in void
tnpc=(npc*)myobj->more;
if (myobj2=tnpc->armour){
if (myobj2->type==81){
stormcloak_last++;
stormcloak_x[stormcloak_last]=myobj->x;
stormcloak_y[stormcloak_last]=myobj->y;
stormcloak_player[stormcloak_last]=tplayer;
if (unsigned long(ett)!=unsigned long(ett-et)){
myobj2->more2++;
if (myobj2->more2>=1024){ //~16-32mins
i2=rnd*1024;
if (!i2){
tnpc->armour=NULL; OBJrelease(myobj2);
tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s storm cloak vanished!"); NET_send(NETplayer,tplayer->net,t);
}//!i2
}//16-32
}//et
}//81
else if (tnpc->negatemagic!=NULL) {goto negatemagic_field;}
}//armour
else if (tnpc->negatemagic!=NULL) {
negatemagic_field:
stormcloak_last++;
stormcloak_x[stormcloak_last]=myobj->x;
stormcloak_y[stormcloak_last]=myobj->y;
stormcloak_player[stormcloak_last]=tplayer;
}
}//->x
}//party
}//i
if (tplayer->party[0]){
if ((tplayer->party[0]->x==368)&&(tplayer->party[0]->y==386)) tplayer->kallor=0;
if (tplayer->kallor){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tplayer->kallor--;
if (tplayer->kallor==0){
static unsigned char tplayer_craft;
tplayer_craft=FALSE;
if (tplayer->craft){
tplayer_craft=TRUE;
if (((tplayer->party[0]->type&1023)==412)||((tplayer->party[0]->type&1023)==414)||((tplayer->party[0]->type&1023)==415)){//exit raft/skiff/boat
myobj2=tplayer->party[0]; //boat (temp, used for positioning)
VLNKremove(tplayer->party[0]); VLNKsremove(tplayer->party[0]); //remove vlnk(s)
if ((tplayer->party[0]->type&1023)==412) tplayer->party[0]->more=tplayer->craft_con; else tplayer->party[0]->more=NULL;
tplayer->party[0]->info=tplayer->party[0]->info&(1<<9);
tplayer->party[0]=tplayer->craft;
tplayer->craft=NULL;
for (i4=7;i4>=0;i4--){ if (tplayer->party[i4]!=NULL){
OBJadd(myobj2->x,myobj2->y,tplayer->party[i4]);
}}
}//412/414/415
//balloon
if ((tplayer->party[0]->type&1023)==423){
myobj2=tplayer->party[0]; //boat (temp, used for positioning)
use_craft(tplayer,myobj2);
}//423
}//craft
for (x4=0;x4<=7;x4++){
if (tplayer->party[x4]){//player is alive (or they would not be listed)
tnpc=(npc*)tplayer->party[x4]->more;
txtset(t,"??"); t->d2[0]=252; t->d2[1]=x4; NET_send(NETplayer,tplayer->net,t);
VLNKremove(tplayer->party[x4]); VLNKsremove(tplayer->party[x4]); //remove VLNK(s)
//only take xp if player is standing on a non-void-type square and not 0,0
if (tplayer->party[x4]->x&&tplayer->party[x4]->y){//not at 0,0
if ((bt[tplayer->party[x4]->y][tplayer->party[x4]->x]&1023)!=0){
if ((bt[tplayer->party[x4]->y][tplayer->party[x4]->x]&1023)!=255){
if ((bt[tplayer->party[x4]->y][tplayer->party[x4]->x]&1023)!=254){
if ((bt[tplayer->party[x4]->y][tplayer->party[x4]->x]&1023)!=253){
if ((bt[tplayer->party[x4]->y][tplayer->party[x4]->x]&1023)!=252){
tnpc->exp-=(tnpc->exp/16);//kal lor
}}}}}
}
if (tnpc->horse){
horsedismount(tplayer->party[x4]);
if (tplayer_craft){
if (HORSEDISMOUNT_HORSEOBJECT){//send horse back to Britain's stables free of charge
OBJmove_allow=TRUE;
OBJmove2(HORSEDISMOUNT_HORSEOBJECT,280,441);
OBJmove2(HORSEDISMOUNT_HORSEOBJECT,279,441);
OBJmove_allow=FALSE;
}
}
}
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[x4],256+128-16,256+128+2); //place avatar on the map
OBJmove_allow=FALSE;
if (tnpc->hp<30) tnpc->hp=30;
tnpc->upflags|=1; //update all
tnpc->flags&=(65535-1); //remove poisoned flag
if (x4==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"\x022KAL LOR!\x022");
NET_send(NETplayer,tplayer->net,t);
}
}}
}//tplayer->kallor==0
}//f
}//tplayer->kallor
}else{//tplayer->party[0]
tplayer->kallor=0;
}
tplayer->ktar_display-=et; if (tplayer->ktar_display<0.0f) tplayer->ktar_display=0;
for (i=0;i<=9;i++){
if (tplayer->ktar_wait[i]){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tplayer->ktar_wait[i]--;
}
//distance check
if (myobj=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
if (myobj2=(object*)tplayer->ktar[i]->more){
x=abs(myobj->x-myobj2->x);
y=abs(myobj->y-myobj2->y);
if ((x>16)||(y>12)) tplayer->ktar_wait[i]=0;
}else{
tplayer->ktar_wait[i]=0;
}
}//->party
}//wait
}//i
//windnew update
if (windnew){
tplayer->windx=0; tplayer->windy=0;
txtset(t,"??"); t->d2[0]=14; t->d2[1]=(windx+1)+(windy+1)*4; NET_send(NETplayer,tplayer->net,t);
}
if (tplayer->xray){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tplayer->xray--;
}
}
if (tplayer->peer){ //peer time reduce
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tplayer->peer--;
}
}
//update midi
if (myobj=tplayer->party[0]){
x=myobj->x; y=myobj->y;
tnpc=(npc*)myobj->more;
// random 50% chance to get theme or forest
i=rnd*2;
if(i==1) {
i=5;//overland: forest midi
}
else {
i=11; //U6 theme
}
if (x>=1024) i=3;//underground: dungeon midi
if ((x>=1024)&&(y>=256)&&(x<1280)&&(y<512)) i=6;//gargoyle lands: xylophone midi
if ((x>=1280)&&(y>=256)&&(x<1351)&&(y<319)) i=1;//castle floor II: britan theme midi
if ((x>=243)&&(y>=307)&&(x<406)&&(y<454)) i=1;//britan: britan theme midi
if ((x>=560)&&(y>=60)&&(x<648)&&(y<120)) i=10;//minoc: stones midi
if ((x>=1024)&&(y>=616)&&(x<1072)&&(y<656)) i=11;//island floor II: forest theme midi
if ((x>=1320)&&(y>=319)&&(x<=1326)&&(y<=324)) i=1;//tower II
if ((x>=1280)&&(y>=344)&&(x<=1336)&&(y<=394)) i=11;//top floor of keep
if ((x>=1242)&&(y>=512)&&(x<=1265)&&(y<=538)) i=11;//underground of keep
if ((x>=220)&&(y>=663)&&(x<=243)&&(y<=688)) i=11;//ground floor of keep
//txtset(t,"??"); t->d2[0]=11; t->d2[1]=7; NET_send(NETplayer,tplayer->net,t);
i2=bt[y][x]&255;
if ((i2>=8)&&(i2<=15)) i=7;
/*
if (tnpc->target!=NULL){ //*FIX THIS
i=9;
}
*/
if ((i2>=16)&&(i2<=47)) goto nomidichange; //shore
if (i!=tplayer->midi){
tplayer->midi=i;
txtset(t,"??"); t->d2[0]=11; t->d2[1]=i; NET_send(NETplayer,tplayer->net,t);
}
}
nomidichange:
/*
if (t->d2[0]==11){ //type 11: set next midi
txtright(t,t->l-1);
nmidi=t->d2[0];
goto CLIENT_donemess;
}//11
*/
for (x=0;x<=7;x++){
if (tplayer->party[x]){
myobj2=tplayer->party[x];
tnpc=(npc*)myobj2->more;
if (tnpc->hp<=0){
//if (tplayer->craft) {tnpc->hp=0; goto exitloop1;} //*2004 TEMP
//death at sea!
if (tplayer->craft){
if (((tplayer->party[0]->type&1023)==412)||((tplayer->party[0]->type&1023)==414)||((tplayer->party[0]->type&1023)==415)){//exit raft/skiff/boat
VLNKremove(tplayer->party[0]); VLNKsremove(tplayer->party[0]); //remove vlnk(s)
if ((tplayer->party[0]->type&1023)==412) tplayer->party[0]->more=tplayer->craft_con; else tplayer->party[0]->more=NULL;
tplayer->party[0]->info=tplayer->party[0]->info&(1<<9);
tplayer->party[0]=tplayer->craft;
tplayer->craft=NULL;
for (i4=7;i4>=0;i4--){
if (tplayer->party[i4]!=NULL){
OBJadd(myobj2->x,myobj2->y,tplayer->party[i4]);
//horse fix for death at sea
horsedismount(tplayer->party[i4]);
if (HORSEDISMOUNT_HORSEOBJECT){//send horse back to Britain's stables free of charge
OBJmove_allow=TRUE;
OBJmove2(HORSEDISMOUNT_HORSEOBJECT,280,441);
OBJmove2(HORSEDISMOUNT_HORSEOBJECT,279,441);
OBJmove_allow=FALSE;
}
}
}
myobj2=tplayer->party[0];
}//412/414/415
//balloon
if ((tplayer->party[0]->type&1023)==423){
use_craft(tplayer,myobj2);
/*VLNKremove(tplayer->party[0]); VLNKsremove(tplayer->party[0]); //remove vlnk(s)
tplayer->party[0]->more=tplayer->craft_con;
tplayer->party[0]->info=tplayer->party[0]->info&(1<<9);
tplayer->party[0]=tplayer->craft;
tplayer->craft=NULL;
for (i4=7;i4>=0;i4--){
if (tplayer->party[i4]!=NULL){
OBJadd(myobj2->x,myobj2->y,tplayer->party[i4]);
}
}
//remove balloon from map + return item to inventory
static mlobj *mmyobj; //array size varies
mmyobj=(mlobj*)myobj2->more;
OBJremove(mmyobj->obj[0]); OBJrelease(mmyobj->obj[0]);
OBJremove(mmyobj->obj[1]); OBJrelease(mmyobj->obj[1]);
OBJremove(mmyobj->obj[2]); OBJrelease(mmyobj->obj[2]);
myobj2->type=420; myobj2->info|=256;
OBJremove(myobj2);
//tnpc=(npc*)tplayer->party[0]->more; //already set!
additemroot(tnpc,myobj2);
tnpc->upflags|=32;*/
myobj2=tplayer->party[0];
}//423
}//death at sea
horsedismount(myobj2);//this won't work at sea (but this is not currently implemented)
login_dead:
VLNKremove(myobj2); VLNKsremove(myobj2); //remove VLNK(s)
x2=myobj2->type;
x3=myobj2->x; y3=myobj2->y;
OBJmove_allow=TRUE;
OBJmove2(myobj2,DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
x4=x2;
if ((x2&1023)==376) x2=339+6*1024;
if ((x2&1023)==377) x2=339+5*1024;
if ((x2&1023)==378) x2=339+3*1024;
if ((x2&1023)==379) x2=339+2*1024;
if ((x2&1023)==380) x2=339+2*1024;
if ((x2&1023)==382) x2=339+4*1024;
if ((x2&1023)==381) x2=339+8*1024; //2004
if ((x2&1023)==383) x2=339+8*1024;
if ((x2&1023)==384) x2=339+5*1024;
if ((x2&1023)==385) x2=339+8*1024;
if ((x2&1023)==386) x2=339+7*1024;
if ((x2&1023)==387) x2=339+3*1024;
if ((x2&1023)==410) x2=339+7*1024;
if ((x2&1023)==363) x2=339+0*1024; //gargoyle! Bah Lem
if ((x2&1023)==354) x2=339+10*1024; //Sherry!
//if (x2!=x4){
if (OBJfindlast(x3,y3)==NULL){ //blood
myobj3=OBJnew();
myobj3->type=338+(int(rnd*3)*1024); myobj3->info|=112;
OBJadd(x3,y3,myobj3);
}
myobj3=OBJnew();
myobj3->type=x2;
myobj3->info|=112;
OBJadd(x3,y3,myobj3);
tnpc->baseitem=tnpc->items; tnpc->baseitem_offset=0;
myobj4=myobj3;
if (x!=0){ //drop inventory items if NOT primary party member
if (tplayer->selected_partymember==x){
tplayer->pathfind=0;
tnpc->order=1;
tplayer->selected_partymember=0;
if (tplayer->party[0]){
tnpc3=(npc*)tplayer->party[0]->more;
tnpc3->order=0;
}
}
if (tnpc->converse!=201){ //only if not a permanent party member
leaveitems2:
if (myobj3=(object*)tnpc->items->more){
OBJremove(myobj3);
OBJadd(myobj4->x,myobj4->y,myobj3);
goto leaveitems2;
}
if (myobj3=tnpc->helm){ tnpc->helm=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
if (myobj3=tnpc->neck){ tnpc->neck=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
if (myobj3=tnpc->wep_left){
if (myobj3->type==(90+1024)) myobj3->type=90;
tnpc->wep_left=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
if (myobj3=tnpc->wep_right){
if (myobj3->type==(90+1024)) myobj3->type=90;
tnpc->wep_right=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
if (myobj3=tnpc->armour){ tnpc->armour=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
if (myobj3=tnpc->ring_left){ tnpc->ring_left=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
if (myobj3=tnpc->ring_right){ tnpc->ring_right=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
if (myobj3=tnpc->boots){ tnpc->boots=NULL; OBJadd(myobj4->x,myobj4->y,myobj3);}
tnpc->baseitem=tnpc->items; tnpc->baseitem_offset=0;
}
tnpc->hp=30;
tnpc->upflags|=1; //update all upon respawn
tnpc->flags&=(65535-1); //remove poisoned flag
//add NPC to resurrect list
for (x4=0;x4<=nresu;x4++){
if (resu[x4]==NULL) goto newresurrect2;
}//x4
nresu++; x4=nresu;
newresurrect2:
resu[x4]=tplayer->party[x];
resu_body[x4]=myobj4;
resu_body_type[x4]=myobj4->type;
resu_wait[x4]=16; //should be 1 hour (but what is host closes during this hour?)
resu_player[x4]=tplayer;
resu_partymember[x4]=x;
resu_x[x4]=myobj4->x; resu_y[x4]=myobj4->y;
}//x!=0
//remove NPC
if (x==0){
tplayer->pathfind=0;
tplayer->kallor=0;
tplayer->px=x3; tplayer->py=y3;
tplayer->selected_partymember=0;
for (x4=1;x4<=7;x4++){
if (tplayer->party[x4]){
horsedismount(tplayer->party[x4]);//this won't work at sea (but this is not currently implemented)
txtset(t,"??"); t->d2[0]=252; t->d2[1]=x4; NET_send(NETplayer,tplayer->net,t);
VLNKremove(tplayer->party[x4]); VLNKsremove(tplayer->party[x4]); //remove VLNK(s)
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[x4],DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
//tplayer->party[x4]=NULL; ***other party members are not really gone!***
}
}//x4
//send online message
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," killed!");
for (x4=0;x4<=playerlist_last;x4++){
if (playerlist[x4]){ //current player
if (playerlist[x4]->net!=NULL){ //net connection available
if (playerlist[x4]->party[0]){
if (playerlist[x4]!=tplayer){
NET_send(NETplayer,playerlist[x4]->net,t);
}}}}}
if (tplayer->karma<=0){ //karma<=0
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[0],DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"An unending darkness engulfs thee...");
NET_send(NETplayer,tplayer->net,t);
//tplayer->idle_connect=64;
/* if player owns a house, then free the house, but don't make a house chest so that its possible to recover the house items.
and making the house chest would be a problem, because its made when logging in*/
if (houseowner(tplayer,tplayer->GNPCflags[28])){
housesav[tplayer->GNPCflags[28]].gold=0;
housesav[tplayer->GNPCflags[28]].flags--; //remove house occupied flag
housesav_update();
tplayer->GNPCflags[28]=0;
}
}else{ //karma>0
//add player to resurrect list
for (x4=0;x4<=nresu;x4++){
if (resu[x4]==NULL) goto newresurrect;
}//x4
nresu++; x4=nresu;
newresurrect:
resu[x4]=tplayer->party[0];
resu_body[x4]=myobj3;
resu_body_type[x4]=myobj3->type;
resu_wait[x4]=16; //should be 1 hour (but what is host closes during this hour?)
resu_player[x4]=tplayer;
resu_partymember[x4]=0;
resu_x[x4]=myobj4->x; resu_y[x4]=myobj4->y;
//like death
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[0],DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
/*
//move player to castle!
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[0],256+128-16,256+128+2); //place avatar on the map
OBJmove_allow=FALSE;
*/
tnpc->hp=30;
tnpc->upflags|=1; //update all upon respawn
tnpc->flags&=(65535-1); //remove poisoned flag
//player *resu_player[65536]; //player object belongs to
//unsigned char resu_partymember[65536]; //party member index
//txtset(t,"?"); t->d2[0]=8; txtadd(t,"An unending darkness engulfs thee... A voice in the darkness intones, \x022KAL LOR!\x022");
if (tplayer->GNPCflags[25]==0) {
txtset(t,"?"); t->d2[0]=8; txtadd(t,"An unending darkness engulfs thee... (press F1 to resurrect)");
}
else {
txtset(t,"?"); t->d2[0]=8; txtadd(t,"An unending darkness engulfs thee... (press F1 to use your insurance and resurrect at healer)");
}
NET_send(NETplayer,tplayer->net,t);
//goto exitloop1;
}//karma
}//x==0
//send message stating the NPC has died
//TESTING
txtset(t,"??"); t->d2[0]=252; t->d2[1]=x; NET_send(NETplayer,tplayer->net,t);
tplayer->party[x]=NULL;
if (!x) inbritanniacheck();
if (login_dead_callback) goto login_dead2;
goto exitloop1;
//replace with dead bodies!!!, and blood!
//myobj=OBJnew();
//myobj->type=
//tplayer->party[x]=NULL;
}//hp<=0
}//active
}//x
exitloop1:;
playerlist[tpl]->globalmessage_wait-=et; if (playerlist[tpl]->globalmessage_wait<0) playerlist[tpl]->globalmessage_wait=0;
playerlist[tpl]->idle+=et;
playerlist[tpl]->idle_connect+=et;
playerlist[tpl]->save_update+=et;
if (!playerlist[tpl]->party[0]) playerlist[tpl]->idle=0; //can't idle if dead
//metalhead*if ((exitrequest)&&(tpl!=0)) {playerlist[tpl]->save_update=-1; goto save_update1;} //update all players!
if (exitrequest) { //update all players!
#ifdef CLIENT
if (tpl) {txtset(t,"??"); t->d2[0]=250; t->d2[1]=1; NET_send(NETplayer,playerlist[tpl]->net,t);} //host quit!
#endif
playerlist[tpl]->save_update=0; goto save_update1;
}
//MessageBox(NULL,"Saving #1","Ultima 6 Online",MB_OK);
//metalhead*if ((playerlist[tpl]->save_update>=512)&&(tpl!=0)) {playerlist[tpl]->save_update=-1; goto save_update1;}
if (playerlist[tpl]->save_update>=512) {playerlist[tpl]->save_update=-1; goto save_update1;}
if (playerlist[tpl]->GNPCflags[253]&1) {playerlist[tpl]->GNPCflags[253]--; goto autoleavebritannia;}
if (playerlist[tpl]->party[0]) x=16; else x=64;
#ifdef CLIENT
if ((playerlist[tpl]->idle_connect>=x)&&(tpl!=0)) goto connect_failed; //(16sec)
if ((playerlist[tpl]->idle>=8192)&&(tpl!=0)){ //remove idle player (not host) (~2 hours)
#else
if ((playerlist[tpl]->idle_connect>=x)) goto connect_failed; //(16sec)
if ((playerlist[tpl]->idle>=8192)){ //remove idle player (not host) (~2 hours)
#endif
connect_failed:
txtset(t,"??"); t->d2[0]=250; t->d2[1]=9; NET_send(NETplayer,playerlist[tpl]->net,t);//leaving britannia (idle)
autoleavebritannia:
//static txt *u6o_user_name=txtnew(); txtset(u6o_user_name,"UNKNOWN");
//static txt *u6o_user_password=txtnew(); txtset(u6o_user_password,"UNKNOWN");
//save player
save_update1:
//MessageBox(NULL,"Saving","Ultima 6 Online",MB_OK);
//U6O_ERRORTAG
if (playerlist[tpl]->name->l==0) goto save_failed;
if (playerlist[tpl]->password->l==0) goto save_failed;
txtset(t,"UNKNOWN");
if (txtsame(playerlist[tpl]->name,t)) goto save_failed;
if (txtsame(playerlist[tpl]->password,t)) goto save_failed;
//find prev savefile
i2=-1;
for (i=0;i<=SAVESLOTLAST;i++){ //search save buffer for player info!
if (save_buffer[i]){
if (txtsame(save_username[i],playerlist[tpl]->name)){
if (txtsame(save_password[i],playerlist[tpl]->password)){
i2=i; //i2=prev file to remove
goto gotprevsave;
}//password
}//name
}//save_buffer[i]
}//i
gotprevsave:
//died from lack of Karma?
if ((playerlist[tpl]->party[0]==NULL)&&(playerlist[tpl]->karma<=0)) goto save_complete; //skip save then remove
//230-237 x,y location of a dead partymember
for (i3=0;i3<=7;i3++) tplayer->GNPCflags[230+i3]=0;//not dead!
for (i3=0;i3<=7;i3++) party_ok[i3]=1;
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_player[i3]==playerlist[tpl]){
party_ok[resu_partymember[i3]]=0;
//set location of dead body
tplayer->GNPCflags[230+resu_partymember[i3]]=resu_x[i3]+(resu_y[i3]<<16);
playerlist[tpl]->party[resu_partymember[i3]]=resu[i3];
}}}
if (playerlist[tpl]->party[0]==NULL) goto save_complete; //ERROR! could not find in resurrection table
tnpc=(npc*)playerlist[tpl]->party[0]->more;
txtset(t,"New Player"); if (txtsame(tnpc->name,t)) goto save_complete; //if a prev savegame exists it will be deleted
//find empty savefile
for (i=0;i<=SAVESLOTLAST;i++){
if (save_buffer[i]==0) goto save_empty;
}
goto save_failed; //ERROR! all savefile slots are full
save_empty:
//implement new password?
if (playerlist[tpl]->newpassword->l){
//check if new password conflicts with existing savegame, if so the password won't change
for (i3=0;i3<=SAVESLOTLAST;i3++){
if (save_buffer[i3]){
if (txtsame(playerlist[tpl]->name,save_username[i3])){
if (txtsame(playerlist[tpl]->newpassword,save_password[i3])){
goto newpassword_unavailable;
}}}}
txtset(playerlist[tpl]->password,playerlist[tpl]->newpassword);
}
newpassword_unavailable:
txtset(playerlist[tpl]->newpassword,"");
txtset(save_username[i],playerlist[tpl]->name);
txtset(save_password[i],playerlist[tpl]->password);
tnpc=(npc*)playerlist[tpl]->party[0]->more; txtset(save_name[i],tnpc->name);
save_buffer[i]=1;
txtset(t4,"");
/*
txtset(t,"??"); t->ds[0]=3; txtadd(t4,t);
*/
txtset(t,"??"); t->ds[0]=SAVEVER; txtadd(t4,t);
if (SAVEVER==5){
txtset(t,"?"); t->d2[0]=PW_ENCRYPTION; txtadd(t4,t);
}
txtset(t,"?"); t->d2[0]=playerlist[tpl]->name->l; txtadd(t4,t); txtadd(t4,playerlist[tpl]->name);
txtset(t,"?"); t->d2[0]=playerlist[tpl]->password->l; txtadd(t4,t); txtadd(t4,playerlist[tpl]->password);
txtset(t,"??"); t->ds[0]=playerlist[tpl]->party[0]->x;
if (party_ok[0]==0) t->ds[0]=256+128-16;
txtadd(t4,t);
txtset(t,"??"); t->ds[0]=playerlist[tpl]->party[0]->y;
if (party_ok[0]==0) t->ds[0]=256+128+2;
txtadd(t4,t);
txtset(t,"?"); t->d2[0]=playerlist[tpl]->male_female; txtadd(t4,t);
txtNEWLEN(t,256*4); memcpy(t->d,&playerlist[tpl]->NPCflags,256*4); txtadd(t4,t);
//GLOBAL FLAG 255=craft type
playerlist[tpl]->GNPCflags[255]=0;
tplayer->GNPCflags[254]=ett;
if (playerlist[tpl]->craft){
if ((playerlist[tpl]->party[0]->type&1023)==412) playerlist[tpl]->GNPCflags[255]=1; //ship
if ((playerlist[tpl]->party[0]->type&1023)==414) playerlist[tpl]->GNPCflags[255]=2; //skiff
if ((playerlist[tpl]->party[0]->type&1023)==415) playerlist[tpl]->GNPCflags[255]=3; //raft
if ((playerlist[tpl]->party[0]->type&1023)==423) playerlist[tpl]->GNPCflags[255]=4; //balloon
}
//*THIS LINE HAS BEEN EDITED TO ONLY ALLOW PRIMARY PLAYER'S CHARACTER TO BE SAVED!
x3=0; for (x2=1;x2<=7;x2++){
//ONLY IF NOT A CORE NPC!
if (playerlist[tpl]->party[x2]){
tnpc3=(npc*)playerlist[tpl]->party[x2]->more;
if (tnpc3->converse==201) x3++;
}
}
playerlist[tpl]->GNPCflags[252]=x3; //no. companion party members
static SYSTEMTIME systime;
GetLocalTime(&systime);
x3=(systime.wDay-1)+(systime.wMonth-1)*32+systime.wYear*(32*12);
playerlist[tpl]->GNPCflags[250]=x3; //250 YMD of last save
if (houseowner(playerlist[tpl],playerlist[tpl]->GNPCflags[28])){
//set number of storage positions
playerlist[tpl]->GNPCflags[29]=housestoragenext[playerlist[tpl]->GNPCflags[28]];
}else{
//NULL house info
playerlist[tpl]->GNPCflags[28]=0; playerlist[tpl]->GNPCflags[29]=0;
//MessageBox(NULL,"HOUSESTORAGECHECK: [28]=0","Ultima 6 Online",MB_OK);
//txtnumint(t9,houseowner_FAILVALUE);
//MessageBox(NULL,t9->d,"Ultima 6 Online",MB_OK);
}
//if playerlist[tpl]->GNPCflags[28]!=0 house is valid
//247&248 TEMP food values for npc 0-7, 1 byte each (only used when saving/loading)
playerlist[tpl]->GNPCflags[247]=0; playerlist[tpl]->GNPCflags[248]=0;
for (x2=0;x2<=7;x2++){ if (playerlist[tpl]->party[x2]){
tnpc3=(npc*)playerlist[tpl]->party[x2]->more;
x3=tnpc3->food;
if (x2==0) playerlist[tpl]->GNPCflags[247]|=x3;
if (x2==1) playerlist[tpl]->GNPCflags[247]|=(x3<<8);
if (x2==2) playerlist[tpl]->GNPCflags[247]|=(x3<<16);
if (x2==3) playerlist[tpl]->GNPCflags[247]|=(x3<<24);
if (x2==4) playerlist[tpl]->GNPCflags[248]|=x3;
if (x2==5) playerlist[tpl]->GNPCflags[248]|=(x3<<8);
if (x2==6) playerlist[tpl]->GNPCflags[248]|=(x3<<16);
if (x2==7) playerlist[tpl]->GNPCflags[248]|=(x3<<24);
}}
txtNEWLEN(t,256*4); memcpy(t->d,&playerlist[tpl]->GNPCflags,256*4); txtadd(t4,t);
txtset(t,"????"); t->df[0]=playerlist[tpl]->karma; txtadd(t4,t);
for(x8=0;x8<=7;x8++){
if (playerlist[tpl]->party[x8]){
tnpc=(npc*)playerlist[tpl]->party[x8]->more;
if ((x8==0)||(tnpc->converse==201)){ //***NOT A U6 NPC***
txtset(t,"??"); t->ds[0]=playerlist[tpl]->party[x8]->type;
if (playerlist[tpl]->craft){
if (x8==0) t->ds[0]=playerlist[tpl]->craft->type;
}
if (tnpc->horse){
//z3=playerlist[tpl]->party[x8]->type>>11;//z3 is the direction of the horse
t->ds[0]=tnpc->originalobjtype;
//exit(tnpc->originalobjtype);
}
txtadd(t4,t); //player type!
txtset(t,"?"); t->d2[0]=tnpc->name->l; txtadd(t4,t); txtadd(t4,tnpc->name);
txtset(t,"??"); t->ds[0]=tnpc->port; txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->hp; txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->hp_max; txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->mp; txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->mp_max; txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->s; txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->d; txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->i; txtadd(t4,t);
txtset(t,"????"); t->dl[0]=tnpc->exp;
//FOLLOWING LINE REMOVED TO ALLOW FOR LOGGING BACK IN AS DEAD
//if (party_ok[x8]==0) t->dl[0]=tnpc->exp-int(tnpc->exp/8); //deduct xp required for ressurection ***FIXED 2005***
txtadd(t4,t);
txtset(t,"??"); t->ds[0]=tnpc->lev; txtadd(t4,t);
txtset(t,"?"); t->d2[0]=tnpc->flags; txtadd(t4,t);
//npc->OBJ
txtset(t,"");
txtset(t2,"????");
x5=0;
for (x2=0;x2<=9;x2++){
if (x2==0) myobj=tnpc->helm;
if (x2==1) myobj=tnpc->wep_right;
if (x2==2) myobj=tnpc->wep_left;
if (x2==3) myobj=tnpc->armour;
if (x2==4) myobj=tnpc->boots;
if (x2==5) myobj=tnpc->neck;
if (x2==6) myobj=tnpc->ring_right;
if (x2==7) myobj=tnpc->ring_left;
if (x2==8) myobj=(object*)tnpc->items; //includes the bag!
if (x2==9) myobj=playerlist[tpl]->mobj; //*ONLY PARTY[0]
if (x8&&(x2==9)) myobj=NULL;
if (myobj){
t2->dl[0]=x5+1; txtadd(t,t2);
}else{
t2->dl[0]=0; txtadd(t,t2); //no object
}
x5=OBJlist(myobj);
}
OBJlist_last=NULL;
housestorageadd0:
//OBJlist->txtlist
for(y6=0;y6<x5;y6++){
t2->ds[0]=OBJlist_list[y6]->type;
t2->ds[1]=OBJlist_list[y6]->info;
//invalid item!
if (obji[sprlnk[OBJlist_list[y6]->type&1023]].weight==0){
if (obji[sprlnk[OBJlist_list[y6]->type&1023]].flags&1024){//CONTAINER!
//bag
t2->ds[0]=OBJ_BAG;//change item type to a bag
t2->ds[1]=112;//set info to avoid conflict
}else{
//rubber duck
t2->ds[0]=169;//ducky
t2->ds[1]=112;//set info to avoid conflict
}
}
txtadd(t,t2);
t2->dl[0]=OBJlist_list[y6]->more2;
//if (housestorageadd){
//txtnumint(t5,t2->ds[0]); txtadd(t5,":type"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
//}
//txtnumint(t5,OBJlist_list[y6]->type&1023);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
if (t2->dl[0]){ //->more!=NULL
if (obji[sprlnk[OBJlist_list[y6]->type&1023]].flags&1024){ //container
for(y7=0;y7<x5;y7++){ //link
if ((object*)OBJlist_list[y6]->more==OBJlist_list[y7]) t2->dl[0]=y7+1;
}//y7
}//multiple
}//->more!=NULL
if (OBJlist_list[y6]->type==448){//horse papers (save)
myobj2=(object*)OBJlist_list[y6]->more;
//latest bug, caused by mose, dunno what he did
//myobj2 is obviously invalid! it should point to the horses head... yet clearly did not!
//step 1. somehow get rid of deed while on horse (such as asking partymember to leave)
//step 2. exit (horse is now released)
//step 3. deed is now stuffed
//if (myobj2==NULL) exit(123);
//NEW GPF THIS LINE! x100!
if (myobj2->x){//horse is not being ridden (so it doesn't matter if we are in a boat or not)
t2->dl[0]=myobj2->x+myobj2->y*2048;//use as few bits as possible(21 bits total)
//21
t2->dl[0]+=(((creature*)myobj2->more)->respawn_x<<21);
//8
//add direction
t2->dl[0]+=(((myobj2->type>>11)&3)<<29);
//2
t->d2[t->l-1]&=225;//11100001b
t->d2[t->l-1]+=(8<<1);//horse without rider!
if (playerlist[tpl]->save_update!=-1){//player is really leaving, remove horse
OBJmove_allow=TRUE;
OBJmove2(myobj2,DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
}
}else{//horse is being ridden by a partymember
t2->dl[0]=0;
//scan to detect which partymember is on that horse
z4=0;
for(z3=0;z3<=7;z3++){
if (myobj3=playerlist[tpl]->party[z3]){
tnpc3=(npc*)myobj3->more;
if ((z3==0)||(tnpc3->converse==201)){
if (tnpc3->horse==myobj2){
//t2->dl[0]=z4;
t2->dl[0]=myobj3->x+myobj3->y*2048;//use as few bits as possible(21 bits total)
//!horse in boat alert! this will set it to 0!
if (playerlist[tpl]->craft){//it MUST be in a boat
t2->dl[0]=2097151;//111111111111111111111b
}
t2->dl[0]+=( ((creature*)((object*)tnpc3->horse)->more)->respawn_x <<21);
//add direction
t2->dl[0]+=(((myobj3->type>>11)&3)<<29);
t->d2[t->l-1]&=225;//11100001b
t->d2[t->l-1]+=(z4<<1);//npc#
goto save_gotridingnpc;
}//tnpc3->horse==myobj2
z4++;
}//converse
}//party[z3]
}//z3
//WARNING! None of the "savable" members of the party are riding this horse!
//at this point the only alternative is that a non-savable partymember is riding the horse
for(z3=0;z3<=7;z3++){
if (myobj3=playerlist[tpl]->party[z3]){
tnpc3=(npc*)myobj3->more;
if ((z3!=0)&&(tnpc3->converse!=201)){
if (tnpc3->horse==myobj2){
t2->dl[0]=myobj3->x+myobj3->y*2048;//use as few bits as possible(21 bits total)
if (playerlist[tpl]->craft){//it MUST be in a boat
//t2->dl[0]=2097151;//111111111111111111111b
//if (HORSEDISMOUNT_HORSEOBJECT){//send horse back to Britain's stables free of charge
//OBJmove_allow=TRUE;
//OBJmove2(HORSEDISMOUNT_HORSEOBJECT,430,280);
//OBJmove2(HORSEDISMOUNT_HORSEOBJECT,429,280);
//OBJmove_allow=FALSE;
t2->dl[0]=280+441*2048;//return horse belonging to temp. partymember to stables in Brit.
//430,280
}
t2->dl[0]+=( ((creature*)((object*)tnpc3->horse)->more)->respawn_x <<21);
//add direction
t2->dl[0]+=(((myobj3->type>>11)&3)<<29);
t->d2[t->l-1]&=225;//11100001b
t->d2[t->l-1]+=(8<<1);//horse without rider!
goto save_gotridingnpc;
}//tnpc3->horse==myobj2
}//converse
}//party[z3]
}//z3
exit (5534);
}//myobj2->x
save_gotridingnpc:;
//save horse "status"
}//horse papers (save)
if (OBJlist_list[y6]->type==149){//deed
myobj2=(object*)OBJlist_list[y6]->more; //myobj2(boat)
if (myobj2==playerlist[tpl]->party[0]){
t2->dl[0]=0xFFFFFFFF;
}else{
t2->dl[0]=myobj2->x+(myobj2->y<<16);
if (playerlist[tpl]->save_update!=-1){
//remove boat (ship)
if ((myobj2->info&2)==0){ //empty boat?
if (t2->dl[0]){ //not in inventory
OBJmove_allow=TRUE;
OBJmove2(myobj2,DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
}//not in inventory
}//empty
}//save_update
}
}//149
txtadd(t,t2);
if (OBJlist_list[y6]->next==NULL) {t2->dl[0]=0; txtadd(t,t2);} //group finished
}//y6
t2->dl[0]=0; txtadd(t,t2); //0+0=all finished
//*ADD LOOP FOR MORE PARTY MEMBERS
txtadd(t4,t);
if (housestorageadd) goto housestorageadd1;
}//NOT A U6 NPC
}//->party[x8]
}//x8 [252]
//save house storage objects
for (x2=0;x2<playerlist[tpl]->GNPCflags[29];x2++){
myobj=(object*)od[housestoragey[playerlist[tpl]->GNPCflags[28]][x2]][housestoragex[playerlist[tpl]->GNPCflags[28]][x2]]->next;
x5=0;
txtset(t,"");
txtset(t2,"????");
x5=OBJlist(myobj);
OBJlist_last=NULL;
housestorageadd=1; goto housestorageadd0;
housestorageadd1: housestorageadd=0;
//remove storage objects ONLY if player is leaving
if (playerlist[tpl]->save_update!=-1){
myobj=(object*)od[housestoragey[playerlist[tpl]->GNPCflags[28]][x2]][housestoragex[playerlist[tpl]->GNPCflags[28]][x2]]->next;
if (myobj){
od[housestoragey[playerlist[tpl]->GNPCflags[28]][x2]][housestoragex[playerlist[tpl]->GNPCflags[28]][x2]]->next=NULL;
OBJcheckflags(housestoragex[playerlist[tpl]->GNPCflags[28]][x2],housestoragey[playerlist[tpl]->GNPCflags[28]][x2]);
}
}//playerlist[tpl]->save_update!=-1
}//x2
/* luteijn 20080731: as of version 4.0 (=2.0), skip encrypting the file!
//ENCRYPT3.0
encrypt(t4);
*/
txtset(t2,".\\save\\"); txtnumint(t,i); txtadd(t,".sav"); txtadd(t2,t);
tfh=open2(t2,OF_READWRITE|OF_SHARE_COMPAT|OF_CREATE);
put(tfh,t4->d2,t4->l);
close(tfh);
/* mose: disabling this new save format for now. I really don't have time to make this work.
luteijn a new format for naming the savegames
txtset(t2,"./save/");
txtset(t,"?/");
t->d[0]=playerlist[tpl]->name->d[0];
if ( (t->d[0] < 'A') || (t->d[0] > 'Z')) {
t->d[0]='@'; // weird character names go here
}
txtadd(t2,t);
txtadd(t2,playerlist[tpl]->name);
txtadd(t2,"-");
txtadd(t2,playerlist[tpl]->npcname);
txtadd(t2,".u6o"); /*idea is to atomically move this over the real save later
LOGadd(t2); // scrlog is client only!
tfh=open2(t2,OF_READWRITE|OF_SHARE_COMPAT|OF_CREATE);
if (tfh->h!=HFILE_ERROR) {
put(tfh,t4->d2,t4->l); /* FIXME: NO RETURN CODE, HOW DO WE KNOW IT WORKED so we can overwrite the existing save?
close(tfh);
/* TODO: if saving went well, move the .u6o file to .sav
} else {
txtset(t,"Failed to open new format savefile");
LOGadd(t);
/* TODO: find out what went wrong and retry.
}*/
// luteijn: sent a time update message at this point
// This is done to keep the times reasonably in sync without sending time too often
// FIXME: use a small function for this eventually.
//send time
txtset(t2,"?"); t2->d2[0]=32;
txtset(t3,"12345678"); t3->dd[0]=btime2;
txtadd(t2,t3);
NET_send(NETplayer,playerlist[tpl]->net,t2);
save_complete:
//remove prev save file for USER_NAME & USER_PASSWORD!
if (i2!=-1){
txtset(t2,".\\save\\"); txtnumint(t,i2); txtadd(t,".sav"); txtadd(t2,t);
DeleteFile(t2->d);
save_buffer[i2]=0;
}
save_failed:
if (playerlist[tpl]->save_update==-1){
for(i3=0;i3<=7;i3++){
if (party_ok[i3]==0) playerlist[tpl]->party[i3]=NULL; //set back to dead
}
playerlist[tpl]->save_update=0;
goto save_update2;
}
//auto-lock house & evict all NPC
if (i4=playerlist[tpl]->GNPCflags[28]){
for (i3=0;i3<housepnext[i4];i3++){
x2=housepx[i4][i3]; y2=housepy[i4][i3];
if (myobj=od[y2][x2]){
housescan0:
if ((myobj->type&1023)==301){//doorway
if (myobj->info&8) myobj2=(object*)myobj->more; else myobj2=myobj;//redirect
if (myobj2->more2){//lock number exists
//door WILL be the first object (for player housing, exceptions exist, such an horse ranch in Britain)
myobj3=od[myobj2->y][myobj2->x];
housescan1:
if (myobj3){
x3=myobj3->type&1023;//GPF
if ((x3<297)||(x3>300)){myobj3=(object*)myobj3->next; goto housescan1;}
myobj3->type&=4095; myobj3->type|=8192;
OBJcheckflags(myobj3->x,myobj3->y);
myobj3=(object*)myobj3->more;
myobj3->type&=4095; myobj3->type|=8192;
OBJcheckflags(myobj3->x,myobj3->y);
}//lock number exists
}//myobj3
}//doorway
if (myobj->info&2){//evict all NPC
myobj2=(object*)myobj->next;//backup ->next pointer
OBJmove_allow=TRUE; OBJmove2(myobj,houseentrancex[i4],houseentrancey[i4]); OBJmove_allow=FALSE;
myobj=myobj2; if (myobj) goto housescan0;
goto housescan2;
}//evict all NPC
if (myobj->info&4 && (myobj->type&1023)==430){//evict horses
myobj2=(object*)myobj->next;//backup ->next pointer
OBJmove_allow=TRUE; OBJmove2(myobj,houseentrancex[i4],houseentrancey[i4]); OBJmove_allow=FALSE;
myobj=myobj2; if (myobj) goto housescan0;
goto housescan2;
}//evict horses
if (myobj=(object*)myobj->next) goto housescan0; //GPF
}//myobj
housescan2:;
}//i3
}//i4 (housenumber)
//disconnect socket
if (playerlist[tpl]->net!=INVALID_NET){
if (socket_disconnect[playerlist[tpl]->net]==0) socket_disconnect[playerlist[tpl]->net]=1;
}
//return CORE NPC party members
for(i3=1;i3<=7;i3++){
if (playerlist[tpl]->party[i3]){
tnpc3=(npc*)playerlist[tpl]->party[i3]->more;
if ((tnpc3->converse)&&(tnpc3->converse!=201)){
horsedismount(playerlist[tpl]->party[i3]);
if (HORSEDISMOUNT_HORSEOBJECT){
OBJmove_allow=TRUE;
OBJmove2(HORSEDISMOUNT_HORSEOBJECT,DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
//ideally horse crt should be deallocated
}
tnpc3->player=NULL;
tnpc3->upflags=0;
tnpc3->order=2; //schedule
tnpc3->follow=NULL;
tnpc3->hp=30;
//tnpc3->exp-=(tnpc->exp/8); ***REMOVED BECAUSE NPC HAS NOT ACTUALLY DIED, JUST LEFT***
tnpc3->flags=0;
OBJmove_allow=TRUE;
OBJmove2(playerlist[tpl]->party[i3],tnpc3->schedule[0].x,tnpc3->schedule[0].y);
OBJmove_allow=FALSE;
playerlist[tpl]->party[i3]=NULL;
}
}
}
//remove any of player's party from resurrect list
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_player[i3]==playerlist[tpl]){
//is this a core NPC (if so then resurrect them at original pos!)
tnpc3=(npc*)resu[i3]->more;
if ((tnpc3->converse)&&(tnpc3->converse!=201)){
tnpc3->player=NULL;
tnpc3->upflags=0;
tnpc3->order=2; //schedule
tnpc3->follow=NULL;
tnpc3->hp=30;
tnpc3->exp-=(tnpc->exp/8);
tnpc3->flags=0;
OBJmove_allow=TRUE;
OBJmove2(resu[i3],tnpc3->schedule[0].x,tnpc3->schedule[0].y);
OBJmove_allow=FALSE;
}
resu[i3]=NULL;
}//player
}//resu
}//i3
if (playerlist[tpl]->party[0]){
tnpc2=(npc*)playerlist[tpl]->party[0]->more;
txtset(t2,"?"); t2->d2[0]=8; txtadd(t2,"Left Britannia: "); txtadd(t2,tnpc2->name);
for (x=0;x<=playerlist_last;x++){
if (playerlist[x]){
if (playerlist[x]->net!=INVALID_NET){
if (x!=tpl){
NET_send(NETplayer,playerlist[x]->net,t2);
}}}}
}
for (i=0;i<=7;i++){ //remove party members from map
if (playerlist[tpl]->party[i]){
VLNKremove(playerlist[tpl]->party[i]); VLNKsremove(playerlist[tpl]->party[i]); //remove VLNK(s)
horsedismount(playerlist[tpl]->party[i]);
if (HORSEDISMOUNT_HORSEOBJECT){
OBJmove_allow=TRUE;
OBJmove2(HORSEDISMOUNT_HORSEOBJECT,DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
//ideally horse crt should be deallocated
}
OBJmove_allow=TRUE;
OBJmove2(playerlist[tpl]->party[i],DEATHPOSX,DEATHPOSY);
OBJmove_allow=FALSE;
}}
//check for house sold evict
if (houseowner(tplayer,tplayer->GNPCflags[28])&&housesav[tplayer->GNPCflags[28]].gold==0){
housesav[tplayer->GNPCflags[28]].flags--; //remove house occupied flag
housesav_update();
}
//free NPC items and structures
for (i=0;i<=7;i++){
x5=0;
if (playerlist[tpl]->party[i]){
tnpc=(npc*)playerlist[tpl]->party[i]->more;
if (i==0){
txtset(t,"Left_Britannia:"); txtadd(t,tnpc->name); LOGadd(t);
myobj=playerlist[tpl]->mobj; //*ONLY PARTY[0]
}
else {
myobj=NULL;
}
if (myobj) x5=OBJlist(myobj);
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
OBJremove(OBJlist_list[y6]); OBJrelease(OBJlist_list[y6]);
}
free(tnpc);
//remove from object update list
if (ouln!=-1){
for (i2=0;i2<=ouln;i2++){
if (playerlist[tpl]->party[i]==oul[i2]){
oul[i2]=NULL;
}}}
OBJremove(playerlist[tpl]->party[i]); OBJrelease(playerlist[tpl]->party[i]);
}//->party
}//i
//free player structure
free(playerlist[tpl]);
playerlist[tpl]=NULL;
inbritanniacheck();
goto idle_skip;
}
save_update2:
//add party to fixed update listq
for (i=0;i<=7;i++){
if (playerlist[tpl]->party[i]){
x=playerlist[tpl]->party[i]->x; y=playerlist[tpl]->party[i]->y;
addupdateobjs_wizardeye:
if (x||y){ //must not be at 0,0, if so it's not on map
//tpx=x-15; tpy=y-11;
//if (tpx<0) tpx=0; if (tpy<0) tpy=0;
//if (tpx>2016) tpx=2016;
//if (tpy>1000) tpy=1000;
getscreenoffset(x,y,&tpx,&tpy);
for (y=-8;y<=(23+8);y++){ for (x=-8;x<=(31+8);x++){
if (((x+tpx)<0)||((y+tpy)<0)||((x+tpx)>2047)||((y+tpy)>1023)) myobj=NULL; else myobj=od[y+tpy][x+tpx];
nextobj2: if (myobj!=NULL){
if (myobj->type==416){//view redirector
if (myobj->more2){
myobj=od[myobj->more2>>16][myobj->more2&65535];
goto nextobj2;
}
}
i3=0;
myobj5=myobj;
//CRASH BANDICOOT
if (myobj5->info&8) myobj5=(object*)myobj5->more; //<-redirect
if (myobj5->info&2) i3=1;
if (myobj5->info&4) i3=1;
if (myobj5->type==(223+1024)) i3=1; //lit powder keg!!!
if (i3==1){
if ((myobj5->info&32768)==0){ //don't add more than once
myobj5->info=myobj5->info|32768; //object is active
ouln++; oul[ouln]=myobj5;
}
}
if (myobj->next!=NULL){myobj=(object*)myobj->next; goto nextobj2;}
} //object exists
}}
}//x||y
}//party member OK
if (i==7){
if (playerlist[tpl]->wizardeyetimeleft){
i++; x=playerlist[tpl]->wizardeyex; y=playerlist[tpl]->wizardeyey; goto addupdateobjs_wizardeye;
}
}
}//i
//2005 objects update message
//assume buffer needs to be resent
//shift buffer to new location
/*
short sobj_bufoffx,sobj_bufoffy; //x,y offset of left corner of entire buffer
unsigned short sobj_buf2bytes[96][72]; //number of 2 byte elements allocated
unsigned short sobj_bufsize[96][72]; //number of 2 byte elements actually used
unsigned short *sobj[96][72]; //scene object raw data
unsigned long sobj_tempfixed[96][72]; //temp fixed objects
*/
static unsigned long bitsi,bitsi2;
static unsigned short *tp2;
static unsigned char sceneupdaterequired;
if (!tplayer->updatemessage){
txtNEWLEN(t,-1048576); //create 1MB buffer
txtNEWLEN(t2,-1048576); //create 1MB buffer
bitsi=0; bitsi2=0;
sceneupdaterequired=0;
z=31;
if (tplayer->resync){
//flush object & mover buffers
tplayer->x=0;
tplayer->y=0;
tplayer->sobj_bufoffx=0;
tplayer->sobj_bufoffy=0;
tplayer->mv_i=0;
for (y=0;y<=71;y++){ for (x=0;x<=95;x++){
tplayer->sobj_bufsize[x][y]=0;
tplayer->sobj_tempfixed[x][y]=0;
}}
z=35;
tplayer->resync=0;
}//resync
BITSadd(t,&bitsi,z,8);//scene update
//txtnumint(t3,t->d2[1]);
//MessageBox(NULL,t3->d,"Ultima 6 Online",MB_OK);
tplayer=playerlist[tpl];
//get player offset
if (myobj=tplayer->party[tplayer->selected_partymember]){
x=myobj->x;
y=myobj->y;
if (tplayer->wizardeyetimeleft){
x=tplayer->wizardeyex; y=tplayer->wizardeyey;
}
}else{
x=tplayer->px; y=tplayer->py; //location where player died
}
//only send if changed
if ((x!=tplayer->x)||(y!=tplayer->y)){
z=1; BITSadd(t,&bitsi,z,1);
BITSadd(t,&bitsi,x,11);
BITSadd(t,&bitsi,y,10);
tplayer->x=x; tplayer->y=y;
sceneupdaterequired=1;
}else{
z=0; BITSadd(t,&bitsi,z,1);
}
//get screen offset
//tpx=x-15; tpy=y-11;
//if (tpx<0) tpx=0; if (tpy<0) tpy=0;
//if (tpx>2016) tpx=2016;
//if (tpy>1000) tpy=1000;
getscreenoffset(x,y,&tpx,&tpy);
//does screen+1 fit inside current buffer?
x3=tpx-1; y3=tpy-1; x4=tpx+32; y4=tpy+24;//screen+1
x5=tplayer->sobj_bufoffx; y5=tplayer->sobj_bufoffy; x6=x5+96-1; y6=y5+72-1; //current buffer extents
//i. if the screen+1 buffer fits within buffer don't relocate
if (x3>=x5){ if (x4<=x6){ if (y3>=y5){ if (y4<=y6){
goto screen1buffershiftcomplete;
}}}}
//ii. clear buffer if screen+1 buffer is entirely outside
i=0;
if (x4<x5) i=1;
if (x3>x6) i=1;
if (y4<y5) i=1;
if (y3>y6) i=1;
if (i){
ZeroMemory(&tplayer->sobj_bufsize,96*72*2); ZeroMemory(&tplayer->sobj_tempfixed,96*72*4);
tplayer->sobj_bufoffx=tpx-32; tplayer->sobj_bufoffy=tpy-24;
goto screen1buffershiftcomplete;
}
//iii. relocate screen+1 buffer
//calculate new buffer location in x2,y2
x2=tplayer->sobj_bufoffx;
if (x2>x3) x2=x3;
if ((x2+95)<x4) x2=x4-95;
y2=tplayer->sobj_bufoffy;
if (y2>y3) y2=y3;
if ((y2+71)<y4) y2=y4-71;
//modified for loop
if (x2>=tplayer->sobj_bufoffx){
if (y2>=tplayer->sobj_bufoffy) i=0; else i=2;
}else{
if (y2>=tplayer->sobj_bufoffy) i=1; else i=3;
}
if (i==0){y9=0; x9=0;}
if (i==1){y9=0; x9=95;}
if (i==2){y9=71; x9=0;}
if (i==3){y9=71; x9=95;}
sobj_copyloop1:
x8=x2-tplayer->sobj_bufoffx+x9; y8=y2-tplayer->sobj_bufoffy+y9;
if (x8>=0){ if (x8<=95){ if (y8>=0){ if (y8<=71){
//copy position
tplayer->sobj_tempfixed[x9][y9]=tplayer->sobj_tempfixed[x8][y8];
i2=tplayer->sobj_buf2bytes[x9][y9]; tplayer->sobj_buf2bytes[x9][y9]=tplayer->sobj_buf2bytes[x8][y8]; tplayer->sobj_buf2bytes[x8][y8]=i2;
tp2=tplayer->sobj[x9][y9]; tplayer->sobj[x9][y9]=tplayer->sobj[x8][y8]; tplayer->sobj[x8][y8]=tp2;
tplayer->sobj_bufsize[x9][y9]=tplayer->sobj_bufsize[x8][y8]; tplayer->sobj_bufsize[x8][y8]=0;
goto sobj_copiedpos1;
}}}}
//clear position
tplayer->sobj_tempfixed[x9][y9]=0;
tplayer->sobj_bufsize[x9][y9]=0;
sobj_copiedpos1:;
if (i==0){
x9++; if (x9>=96){y9++; x9=0;}
if (y9<72) goto sobj_copyloop1;
}
if (i==1){
x9--; if (x9<0){y9++; x9=95;}
if (y9<72) goto sobj_copyloop1;
}
if (i==2){
x9++; if (x9>=96){y9--; x9=0;}
if (y9>=0) goto sobj_copyloop1;
}
if (i==3){
x9--; if (x9<0){y9--; x9=95;}
if (y9>=0) goto sobj_copyloop1;
}
tplayer->sobj_bufoffx=x2; tplayer->sobj_bufoffy=y2;
screen1buffershiftcomplete:
//is screen+1 of buffer and visual area EXACTLY THE SAME?
static unsigned char screenplus1check;
screenplus1check=1;
goto screenplus1check_entry;
screenplus1check_return:
screenplus1check=0;
//screen+1 was NOT exactly the same, so perform a screen+8 update
sceneupdaterequired=1;
z=1; BITSadd(t,&bitsi,z,1);//screen+8 update required
x3=tpx-8; y3=tpy-8; x4=tpx+32+8-1; y4=tpy+24+8-1;
x5=tplayer->sobj_bufoffx; y5=tplayer->sobj_bufoffy; x6=x5+96-1; y6=y5+72-1; //current buffer extents
//i. if the screen+8 buffer fits within buffer don't relocate
if (x3>=x5){ if (x4<=x6){ if (y3>=y5){ if (y4<=y6){
goto bufferrelocatecomplete0;
}}}}
//ii. clear buffer if screen+8 buffer is entirely outside
i=0;
if (x4<x5) i=1;
if (x3>x6) i=1;
if (y4<y5) i=1;
if (y3>y6) i=1;
if (i){
ZeroMemory(&tplayer->sobj_bufsize,96*72*2); ZeroMemory(&tplayer->sobj_tempfixed,96*72*4);
tplayer->sobj_bufoffx=tpx-32; tplayer->sobj_bufoffy=tpy-24;
//MessageBox(NULL,"shiftbuffer: entire buffer cleared","Ultima 6 Online",MB_OK);
goto bufferrelocatecomplete0;
}
//iii. relocate buffer
//calculate new buffer location in x2,y2
x2=tplayer->sobj_bufoffx;
if (x2>x3) x2=x3;
if ((x2+95)<x4) x2=x4-95;
y2=tplayer->sobj_bufoffy;
if (y2>y3) y2=y3;
if ((y2+71)<y4) y2=y4-71;
//modified for loop
if (x2>=tplayer->sobj_bufoffx){
if (y2>=tplayer->sobj_bufoffy) i=0; else i=2;
}else{
if (y2>=tplayer->sobj_bufoffy) i=1; else i=3;
}
if (i==0){y9=0; x9=0;}
if (i==1){y9=0; x9=95;}
if (i==2){y9=71; x9=0;}
if (i==3){y9=71; x9=95;}
sobj_copyloop:
x8=x2-tplayer->sobj_bufoffx+x9; y8=y2-tplayer->sobj_bufoffy+y9;
if (x8>=0){ if (x8<=95){ if (y8>=0){ if (y8<=71){
//copy position
tplayer->sobj_tempfixed[x9][y9]=tplayer->sobj_tempfixed[x8][y8];
i2=tplayer->sobj_buf2bytes[x9][y9]; tplayer->sobj_buf2bytes[x9][y9]=tplayer->sobj_buf2bytes[x8][y8]; tplayer->sobj_buf2bytes[x8][y8]=i2;
tp2=tplayer->sobj[x9][y9]; tplayer->sobj[x9][y9]=tplayer->sobj[x8][y8]; tplayer->sobj[x8][y8]=tp2;
tplayer->sobj_bufsize[x9][y9]=tplayer->sobj_bufsize[x8][y8]; tplayer->sobj_bufsize[x8][y8]=0;
goto sobj_copiedpos0;
}}}}
//clear position
tplayer->sobj_tempfixed[x9][y9]=0;
tplayer->sobj_bufsize[x9][y9]=0;
sobj_copiedpos0:;
if (i==0){
x9++; if (x9>=96){y9++; x9=0;}
if (y9<72) goto sobj_copyloop;
}
if (i==1){
x9--; if (x9<0){y9++; x9=95;}
if (y9<72) goto sobj_copyloop;
}
if (i==2){
x9++; if (x9>=96){y9--; x9=0;}
if (y9>=0) goto sobj_copyloop;
}
if (i==3){
x9--; if (x9<0){y9--; x9=95;}
if (y9>=0) goto sobj_copyloop;
}
tplayer->sobj_bufoffx=x2; tplayer->sobj_bufoffy=y2;
//MessageBox(NULL,"shiftbuffer: buffer shifted","Ultima 6 Online",MB_OK);
bufferrelocatecomplete0:
//ERROR is it overwriting data it needs to read as it goes
//OPTOMIZATION!!! switch the pointers to the data and data buffer lengths instead of the data
//[17:25] galleondragon: and screen+8 area is reloaded in centre
/*
for (y9=0;y9<=71;y9++){
for (x9=0;x9<=95;x9++){
if (tplayer->sobj_tempfixed[x9][y9]||tplayer->sobj_bufsize[x9][y9]){
objbufferf->graphic->o2[x9+y9*96]=0xFFFF;
}else{
objbufferf->graphic->o2[x9+y9*96]=31;
}
}}
*/
//MessageBox(NULL,"update required","Ultima 6 Online",MB_OK);
screenplus1check_entry:
//refresh pathfinding array
//if (tplayer->xray){ //xray!
//for (x2=0;x2<=65535;x2++) pfa[x2]=PFs+PFd;
//}else{
//pathfind2(x,y,NULL);
//}
//buffer must be updated while message is created!
static long mapx,mapy,bufx,bufy;
static unsigned short vbuf[1024];
for (y=0;y<=39;y++){ for (x=0;x<=47;x++){
mapx=tpx+x-8; mapy=tpy+y-8; bufx=mapx-tplayer->sobj_bufoffx; bufy=mapy-tplayer->sobj_bufoffy;
/*
x4=0; z4=2;
for (y=0;y<=25;y++){ for (x=0;x<=33;x++){
if (pfa[x+y*256+257]&(PFs+PFd)) z5=1; else z5=0;
if (z5!=z4){
if (z4!=2){ //not the first pass
*p=x4+z4*128; p++;
}//z4!=2
x4=0; //number of squares in a row -1
z4=z5; //type (1 or 0)
}else{
if (x4==127){
*p=127+z4*128; p++;
x4=0;
}else{
x4++;
}
}
}}//x,y
*p=x4+z4*128; p++; //save last row
*/
if (screenplus1check){
if (x<7) goto objbufnoupdate0; if (y<7) goto objbufnoupdate0; if (x>40) goto objbufnoupdate0; if (y>32) goto objbufnoupdate0;
}
i=0;
if (mapx<0) goto objbuffer_outofrange; if (mapx>2047) goto objbuffer_outofrange; if (mapy<0) goto objbuffer_outofrange; if (mapy>1023) goto objbuffer_outofrange;
myobj=od[mapy][mapx];
objskip0: if (myobj){
if (objvisible(tplayer,myobj)==NULL){
myobj=(object*)myobj->next;
goto objskip0;
}
if (myobj->type==416){//view redirector
if (myobj->more2){
bt[mapy][mapx]=bt[myobj->more2>>16][myobj->more2&65535];
mapx=myobj->more2&65535; mapy=myobj->more2>>16;
myobj=od[myobj->more2>>16][myobj->more2&65535];
goto objskip0;
}
}//view redirector
if (!tclass_object[myobj->type]){
myobj=(object*)myobj->next;
goto objskip0;
}
}//myobj
if (i3=tobjfixed_index[mapy][mapx]){
i4=tobjfixed_type[i3];
i5=1;
i6=1;
z3=getnbits(i4);
for (i2=i3+1;i2<=(i3+i4);i2++){
if (myobj){
if ((myobj->type&1023)==OBJ_BLOOD) goto noflash0;//blood
if ((myobj->type&1023)==OBJ_FIRE_FIELD) goto noflash0;//317 fire field
if ((myobj->type&1023)==OBJ_POISON_FIELD) goto noflash0;//318 poison field
if ((myobj->type&1023)==OBJ_PROTECTION_FIELD) goto noflash0;//319 protection field
if ((myobj->type&1023)==OBJ_SLEEP_FIELD) goto noflash0;//320 sleep field
if ((myobj->type&1023)==OBJ_WEB) goto noflash0;//53 web
if ((myobj->type&1023)==OBJ_RED_GATE){//red gate
if (((myobj->info&112)>>4)>=2) i6=0;
goto noflash0;
}//red gate
if ((myobj->info&112)==16) i6=0;
noflash0:
if (objvisible(tplayer,myobj)==NULL) myobj=(object*)myobj->next;
}
if (myobj&&i6){
if (myobj->type==tobjfixed_type[i2]){//object still exists
if (tplayer->sobj_tempfixed[bufx][bufy]&i5){//but buffer flag is set, saying it is not there!
if (screenplus1check) goto screenplus1check_return; //********SCREENPLUS1CHECK********
tplayer->sobj_tempfixed[bufx][bufy]-=i5;
z=1; BITSadd(t,&bitsi,z,1);//edit another tempfixed object
z=y*48+x; BITSadd(t,&bitsi,z,11);//x,y offset
if (z3){z=i2-i3-1; BITSadd(t,&bitsi,z,z3);}//which tempfixed obj
//MessageBox(NULL,"tempfixed change","Ultima 6 Online",MB_OK);
}//sobj_tempfixed[bufx][bufy]&i5
myobj=(object*)myobj->next;
}else{//object does not exist
if ((tplayer->sobj_tempfixed[bufx][bufy]&i5)==0){
if (screenplus1check) goto screenplus1check_return; //********SCREENPLUS1CHECK********
tplayer->sobj_tempfixed[bufx][bufy]|=i5;
z=1; BITSadd(t,&bitsi,z,1);//edit another tempfixed object
z=y*48+x; BITSadd(t,&bitsi,z,11);//x,y offset
if (z3){z=i2-i3-1; BITSadd(t,&bitsi,z,z3);}//which tempfixed obj
//MessageBox(NULL,"tempfixed change","Ultima 6 Online",MB_OK);
i6=0;
}//(sobj_tempfixed[bufx][bufy]&i5)==0
}
}else{
//object is not present
if ((tplayer->sobj_tempfixed[bufx][bufy]&i5)==0){
if (screenplus1check) goto screenplus1check_return; //********SCREENPLUS1CHECK********
tplayer->sobj_tempfixed[bufx][bufy]|=i5;
z=1; BITSadd(t,&bitsi,z,1);//edit another tempfixed object
z=y*48+x; BITSadd(t,&bitsi,z,11);//x,y offset
if (z3){z=i2-i3-1; BITSadd(t,&bitsi,z,z3);}//which tempfixed obj
//MessageBox(NULL,"tempfixed change","Ultima 6 Online",MB_OK);
}//(sobj_tempfixed[bufx][bufy]&i5)==0
}
i5<<=1;
}//i2
}//tobjfixed_index[mapy][mapx]
wizardeyesadded=0;
nextbufobj0: if (myobj){
if (objvisible(tplayer,myobj)==NULL){
myobj=(object*)myobj->next;
goto nextbufobj0;
}
if (!tclass_object[myobj->type]){
myobj=(object*)myobj->next;
goto nextbufobj0;
}
vbuf[i]=myobj->type;
if ((myobj->type&1023)==OBJ_BLOOD) goto noflash1;//blood
if ((myobj->type&1023)==OBJ_FIRE_FIELD) goto noflash1;//317 fire field
if ((myobj->type&1023)==OBJ_POISON_FIELD) goto noflash1;//318 poison field
if ((myobj->type&1023)==OBJ_PROTECTION_FIELD) goto noflash1;//319 protection field
if ((myobj->type&1023)==OBJ_SLEEP_FIELD) goto noflash1;//320 sleep field
if ((myobj->type&1023)==OBJ_WEB) goto noflash1;//53 web
if ((myobj->type&1023)==OBJ_RED_GATE){//red gate
if (((myobj->info&112)>>4)>=2) vbuf[i]|=32768;
goto noflash1;
}//red gate
if ((myobj->info&112)==16) vbuf[i]|=32768;
noflash1:
i++;
myobj=(object*)myobj->next; goto nextbufobj0;
}//myobj
//add wizard eye if necessary
if (!wizardeyesadded){
for (wizardeyesi2=1; wizardeyesi2<=wizardeyesi; wizardeyesi2++){
if (mapx==wizardeyesx[wizardeyesi2]){ if (mapy==wizardeyesy[wizardeyesi2]){
if (tplayer->wizardeyetimeleft){
if ((tplayer->wizardeyex==mapx)&&(tplayer->wizardeyey==mapy)) goto wizardeyesloopnext;
}
wizardeyesadded=1;
myobj=wizardeyesobj;
goto nextbufobj0;
wizardeyesloopnext:;
}}//x,y
}//wizardeyesi2
}//!wizardeyesadded
//short sobj_bufoffx,sobj_bufoffy; //x,y offset of left corner of entire buffer
//unsigned short sobj_buf2bytes[96][72]; //number of 2 byte elements allocated
//unsigned short sobj_bufsize[96][72]; //number of 2 byte elements actually used
//unsigned short *sobj[96][72]; //scene object raw data
//unsigned long sobj_tempfixed[96][72]; //temp fixed objects
//compare buffers
//length check
objbuffer_outofrange:
if (tplayer->sobj_bufsize[bufx][bufy]!=i) goto objbufupdate0;
if (i==0) goto objbufnoupdate0;
tp2=tplayer->sobj[bufx][bufy];
for (i2=0;i2<i;i2++){
if (tp2[i2]!=vbuf[i2]) goto objbufupdate0;
}
goto objbufnoupdate0;
objbufupdate0:
if (screenplus1check) goto screenplus1check_return; //********SCREENPLUS1CHECK********
//update allocated buffer size
if (tplayer->sobj_buf2bytes[bufx][bufy]<i){
if (tplayer->sobj[bufx][bufy]) free(tplayer->sobj[bufx][bufy]);
tplayer->sobj[bufx][bufy]=(unsigned short*)malloc(i*2);
tplayer->sobj_buf2bytes[bufx][bufy]=i;
}
z=1; BITSadd(t2,&bitsi2,z,1);//1 edit objects of another square
z=y*48+x; BITSadd(t2,&bitsi2,z,11);//11 screen offset of square
//update buffer info
tp2=tplayer->sobj[bufx][bufy];
for (i2=0;i2<i;i2++){
tp2[i2]=vbuf[i2];
z=1; BITSadd(t2,&bitsi2,z,1);
z=vbuf[i2]&(65535-32768); BITSadd(t2,&bitsi2,z,16);//10 object graphic index (optomized ***YET TO BE OPTOMIZED***)
z=0; if (vbuf[i2]&32768) z=1;
BITSadd(t2,&bitsi2,z,1);
}//i2
z=0; BITSadd(t2,&bitsi2,z,1);
tplayer->sobj_bufsize[bufx][bufy]=i;
/*
1 edit objects of another square
{
11 screen offset of square
{
1 a/another object exists on this square
10 object graphic index (optomized)
1 object is flashing
}
}
*/
//...
objbufnoupdate0:;
//***** DONT FORGET FLASHING OBJECTS HERE AND IN TEMPFIXED BUFFER
//***** DONT FORGET NOT TO UPDATE BLACKED OUT SQUARES
//or off screen
}}
if (screenplus1check){
screenplus1check=0;
z=0; BITSadd(t,&bitsi,z,1);//screen+8 update unnecessary
}else{
z=0; BITSadd(t,&bitsi,z,1);//no more tempfixed objects
z=0; BITSadd(t2,&bitsi2,z,1);//no more squares of objects to edit
}
//add second bitstream to first bitstream
if (bitsi2){
i=0; i2=bitsi2>>3;//i2 is number of whole bytes
for (i=0;i<i2;i++){
BITSadd(t,&bitsi,t2->d2[i],8);
}
i3=bitsi2%8; if (i3) BITSadd(t,&bitsi,t2->d2[i2],i3);
}
//mover update
//create new mover list
i=-1;
for (y=0;y<=25;y++){ for (x=0;x<=33;x++){
mapx=tpx+x-1; mapy=tpy+y-1;
if (mapx<0) goto moverbuffer_outofrange; if (mapx>2047) goto moverbuffer_outofrange; if (mapy<0) goto moverbuffer_outofrange; if (mapy>1023) goto moverbuffer_outofrange;
myobj=od[mapy][mapx];
mvobjskip: if (myobj){
if (myobj->type==416){//view redirector
if (myobj->more2){
bt[mapy][mapx]=bt[myobj->more2>>16][myobj->more2&65535];
mapx=myobj->more2&65535; mapy=myobj->more2>>16;
myobj=od[myobj->more2>>16][myobj->more2&65535];
goto mvobjskip;
}
}//view redirector
if (!tclass_mover[myobj->type]){
myobj=(object*)myobj->next;
goto mvobjskip;
}
//object is a mover class
//check for npc or crt pointer
//XXXX UNOCCUPIED BOATS, SKIFFS, RAFTS WON'T HAVE A CRT OR NPC POINTER
//if ((myobj->info&(2+4))==0){
//myobj=(object*)myobj->next;
//goto mvobjskip;
//}
if (!myobj->more){ if ((myobj->type&1023)!=414){ if ((myobj->type&1023)!=415){//not a raft or skiff
myobj=(object*)myobj->next;
goto mvobjskip;
}}}
//add it to the list
i++;
mv_object[i]=myobj;
mv_x[i]=tpx+x-1; mv_y[i]=tpy+y-1;
mv_type[i]=myobj->type&1023;
mv_dir[i]=objgetdir(myobj->type);
mv_frame[i]=OBJGETDIR_FRAME;
mv_flags[i]=0; mv_playerid[i]=0; mv_hpmp[i]=0; mv_ktar[i]=0; mv_more[i]=0;
if (mv_type[i]==366) mv_frame[i]=myobj->type>>10;//EXCEPTION: tanglevine tendril
if (mv_type[i]==413) mv_frame[i]=myobj->type>>10;//EXCEPTION: silver serpent
if (myobj->info&2){//npc
tnpc=(npc*)myobj->more;
//horse with rider? set more
if (mv_type[i]==431){
mv_more[i]=tnpc->originalobjtype&1023;
}
if (tnpc->protection) mv_flags[i]|=MV_PROTECT;
if (tnpc->light) mv_flags[i]|=MV_LIGHTBRIGHT;
if (myobj3=tnpc->armour){
if (myobj3->type==81) mv_flags[i]|=MV_STORMCLOAK; //storm cloak
}//armour
//NEWCODE
if (tnpc->negatemagic){
mv_flags[i]|=MV_STORMCLOAK; //storm cloak
}//negatemagic
//NEWCODEEND
if (tnpc->flags&2) mv_flags[i]|=MV_INVISIBLE;
if (tnpc->flags&4) mv_flags[i]|=MV_SLEEP;
if (tplayer2=tnpc->player){//has player pointer
if (tnpc->light==0){
if (tnpc->player==tplayer) mv_flags[i]|=MV_LIGHTGLOW;
}//light
if (tplayer2->party[0]==myobj){//first player
mv_playerid[i]=tplayer2->id;
if (tplayer2->typing){
if (tplayer!=tplayer2) mv_flags[i]|=MV_TYPING;
}//typing
if (tplayer2->speaking){
if (tplayer!=tplayer2) mv_flags[i]|=MV_SPEAKING;
}//speaking
//hp/mp bars 0-15hp, 0-7mp, 1poisioned
f=(float)tnpc->hp/(float)tnpc->hp_max; z=f*16; if (z==16) z=15;
f=(float)tnpc->mp/(float)tnpc->mp_max; z2=f*8; if (z2==8) z2=7;
z=z+(z2<<4); if (tnpc->flags&1) z+=128;
mv_hpmp[i]=z;
}//tplayer2->party[0]==myobj
}else{//no player pointer
if (tnpc->schedule){
if (tnpc->schedule_i!=-1){
if (tnpc->schedule[tnpc->schedule_i].type==0x91) mv_flags[i]|=MV_SLEEP; //0x91=sleeping!
}//tnpc->schedule_i!=-1
}//tnpc->schedule
}//no player pointer
}//npc
if (myobj->info&4){//crt
crt=(creature*)myobj->more;
if (crt->flags&8) mv_flags[i]|=MV_PARALYZE;
if (crt->flags&4) mv_flags[i]|=MV_SLEEP;
if (crt->flags&2){
if (crt->al==1){i--; goto mover_add_complete;}//creature is not friendly allegiance, don't display at all
mv_flags[i]|=MV_INVISIBLE;
}
for (z=0;z<=9;z++){
if (tplayer->ktar_wait[z]){
if ((object*)tplayer->ktar[z]->more==myobj){
mv_ktar[i]=z+1;
}
}
}//z
}//crt
mover_add_complete:
myobj=(object*)myobj->next; goto mvobjskip;
}//myobj
moverbuffer_outofrange:;
}}
mv_i=i+1;
//compare to current mover list
ZeroMemory(&mv_last,sizeof(mv_last));
ZeroMemory(&mv_new,sizeof(mv_new));
//******this code happens whether or not an update is sent******
//remove all offscreen objects in client's array
i=0;
mover_removeoffscreen_next: if (i<tplayer->mv_i){
x=tplayer->mv_x[i]-tpx; y=tplayer->mv_y[i]-tpy;
if ((x<-1)||(x>32)||(y<-1)||(y>24)){
//reshuffle array
for (i3=i+1;i3<tplayer->mv_i;i3++){
tplayer->mv_x[i3-1]=tplayer->mv_x[i3];
tplayer->mv_y[i3-1]=tplayer->mv_y[i3];
tplayer->mv_type[i3-1]=tplayer->mv_type[i3];
tplayer->mv_dir[i3-1]=tplayer->mv_dir[i3];
tplayer->mv_frame[i3-1]=tplayer->mv_frame[i3];
tplayer->mv_object[i3-1]=tplayer->mv_object[i3];
tplayer->mv_flags[i3-1]=tplayer->mv_flags[i3];
tplayer->mv_hpmp[i3-1]=tplayer->mv_hpmp[i3];
tplayer->mv_playerid[i3-1]=tplayer->mv_playerid[i3];
tplayer->mv_ktar[i3-1]=tplayer->mv_ktar[i3];
tplayer->mv_more[i3-1]=tplayer->mv_more[i3];
}//i3
tplayer->mv_i--;
goto mover_removeoffscreen_next;
}//x,y boundary check
i++; goto mover_removeoffscreen_next;
}//i check
//1. REMOVE
i=0;
mover_removecheck_next: if (i<tplayer->mv_i){
for (i2=0;i2<mv_i;i2++){
if (mv_new[i2]==0){
//is new x,y offset out of range? if so the object will be removed and recreated
x=mv_x[i2]-tplayer->mv_x[i];
if (abs(x)>3) goto mover_remove_outofrange;
y=mv_y[i2]-tplayer->mv_y[i];
if (abs(y)>3) goto mover_remove_outofrange;
if (mover_offseti[x+3][y+3]==255) goto mover_remove_outofrange;
if (tplayer->mv_type[i]==mv_type[i2]){
if (tplayer->mv_type[i]==413){//silver serp
if (x||y) goto mover_remove_outofrange;
if (tplayer->mv_frame[i]!=mv_frame[i2]) goto mover_remove_outofrange;
goto mover_remove_link;
}
if (tplayer->mv_type[i]==366){//tanglevine tendril (not core)
if (x||y) goto mover_remove_outofrange;
if (tplayer->mv_frame[i]!=mv_frame[i2]) goto mover_remove_outofrange;
goto mover_remove_link;
}
if (tplayer->mv_object[i]==mv_object[i2]){//obj check
mover_remove_link:
if (tplayer->mv_playerid[i]==mv_playerid[i2]){
mv_last[i]=i2; mv_new[i2]=MOVER_FOUND;//link
i++; goto mover_removecheck_next;
}//playerid
}//object
}//type
}//mv_new[i2]==0
mover_remove_outofrange:;
}//i2
//remove mover i message
BITSadd(t,&bitsi,1,1);//remove a/another mover
BITSadd(t,&bitsi,i,getnbits(tplayer->mv_i));//index of mover to remove based on current buffer
sceneupdaterequired=1;
//reshuffle array
for (i3=i+1;i3<tplayer->mv_i;i3++){
tplayer->mv_x[i3-1]=tplayer->mv_x[i3];
tplayer->mv_y[i3-1]=tplayer->mv_y[i3];
tplayer->mv_type[i3-1]=tplayer->mv_type[i3];
tplayer->mv_dir[i3-1]=tplayer->mv_dir[i3];
tplayer->mv_frame[i3-1]=tplayer->mv_frame[i3];
tplayer->mv_object[i3-1]=tplayer->mv_object[i3];
tplayer->mv_flags[i3-1]=tplayer->mv_flags[i3];
tplayer->mv_hpmp[i3-1]=tplayer->mv_hpmp[i3];
tplayer->mv_playerid[i3-1]=tplayer->mv_playerid[i3];
tplayer->mv_ktar[i3-1]=tplayer->mv_ktar[i3];
tplayer->mv_more[i3-1]=tplayer->mv_more[i3];
}//i3
tplayer->mv_i--;
goto mover_removecheck_next;
}//i check
z=0; BITSadd(t,&bitsi,z,1);//no more movers to remove
//2.1 MOVE MOVER
for (i=0;i<tplayer->mv_i;i++){
i2=mv_last[i];
x=mv_x[i2]-tplayer->mv_x[i]; y=mv_y[i2]-tplayer->mv_y[i];
if (x||y){
sceneupdaterequired=1;
BITSadd(t,&bitsi,1,1);//move a/another mover
BITSadd(t,&bitsi,i,getnbits(tplayer->mv_i));//index of mover to move in current buffer
BITSadd(t,&bitsi,mover_offseti[x+3][y+3],5);
//update client data
//HORSE SWAP FIX (HORSE FIX)
if ( (tplayer->mv_type[i]==431) &&
//( ((mv_dir[i2]==0)&&(mv_x[i2]!=tplayer->mv_x[i]) ) || ((mv_dir[i2]==1)&&(mv_y[i2]!=tplayer->mv_y[i])) || ((mv_dir[i2]==2)&&(mv_x[i2]!=tplayer->mv_x[i])) || ((mv_dir[i2]==3)&&(mv_y[i2]!=tplayer->mv_y[i])) )
( ((mv_dir[i2]==0)&& ((mv_x[i2]!=tplayer->mv_x[i])||(mv_y[i2]>=tplayer->mv_y[i])) ) || ((mv_dir[i2]==1)&&((mv_y[i2]!=tplayer->mv_y[i])||(mv_x[i2]<=tplayer->mv_x[i])) ) || ((mv_dir[i2]==2)&&((mv_x[i2]!=tplayer->mv_x[i])||(mv_y[i2]<=tplayer->mv_y[i])) ) || ((mv_dir[i2]==3)&&((mv_y[i2]!=tplayer->mv_y[i])||(mv_x[i2]>=tplayer->mv_x[i])) ) )
){
//NOHORSEFIXNECESSARY code negates the HORSE SWAP FIX patch under certain conditions to allow for diagonal movement with a frame change
if ((mv_dir[i2]==0)&&(mv_y[i2]<tplayer->mv_y[i])) goto NOHORSEFIXNECESSARY;
if ((mv_dir[i2]==2)&&(mv_y[i2]>tplayer->mv_y[i])) goto NOHORSEFIXNECESSARY;
tplayer->mv_x[i]=mv_x[i2];
tplayer->mv_y[i]=mv_y[i2];
//change client frame number to trick the server into sending a dir/frame update message too
if (tplayer->mv_frame[i]==mv_frame[i2]){
tplayer->mv_frame[i]++; if (tplayer->mv_frame[i]==2) tplayer->mv_frame[i]=0;
}
}else{
NOHORSEFIXNECESSARY:
tplayer->mv_x[i]=mv_x[i2];
tplayer->mv_y[i]=mv_y[i2];
tplayer->mv_dir[i]=mv_dir[i2];
tplayer->mv_frame[i]=mv_frame[i2];
}//HORSE SWAP FIX
}//x||y
}//i
BITSadd(t,&bitsi,0,1);//no more movers to move
//2.2 MOVER DIRECTION/FRAME CHANGE
/*
1 change mover frame/dir
? index of mover
[2] if mover CAN have a direction it is set here, otherwise this can be omitted and the movers frame only will be incremented
*/
for (i=0;i<tplayer->mv_i;i++){
i2=mv_last[i];
if ((tplayer->mv_dir[i]!=mv_dir[i2])||(tplayer->mv_frame[i]!=mv_frame[i2])){
BITSadd(t,&bitsi,1,1);
BITSadd(t,&bitsi,i,getnbits(tplayer->mv_i));//index of mover to move in current buffer
BITSadd(t,&bitsi,mv_dir[i2],2);
tplayer->mv_dir[i]=mv_dir[i2];
tplayer->mv_frame[i]=mv_frame[i2];
sceneupdaterequired=1;
}
}//i
BITSadd(t,&bitsi,0,1);//no more movers to direction/frame change
//2.3 MOVER STATE CHANGE
z3=getnbits(tplayer->mv_i);
for (i=0;i<tplayer->mv_i;i++){
i2=mv_last[i];
i3=0;
if ((tplayer->mv_flags[i]&MV_LIGHTBRIGHT)!=(mv_flags[i2]&MV_LIGHTBRIGHT)){
if (mv_flags[i2]&MV_LIGHTGLOW){ if (tplayer->mv_flags[i]&MV_LIGHTBRIGHT){
goto MV_LIGHTBRIGHT_assumed;
}}
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,0,4);
}
MV_LIGHTBRIGHT_assumed:
if ((tplayer->mv_flags[i]&MV_LIGHTGLOW)!=(mv_flags[i2]&MV_LIGHTGLOW)){
if (mv_flags[i2]&MV_LIGHTBRIGHT){ if (tplayer->mv_flags[i]&MV_LIGHTGLOW){
goto MV_LIGHTGLOW_assumed;
}}
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,1,4);
}
MV_LIGHTGLOW_assumed:
if ((tplayer->mv_flags[i]&MV_INVISIBLE)!=(mv_flags[i2]&MV_INVISIBLE)){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,2,4);
}
if ((tplayer->mv_flags[i]&MV_PARALYZE)!=(mv_flags[i2]&MV_PARALYZE)){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,3,4);
}
if ((tplayer->mv_flags[i]&MV_SLEEP)!=(mv_flags[i2]&MV_SLEEP)){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,4,4);
}
if ((tplayer->mv_flags[i]&MV_PROTECT)!=(mv_flags[i2]&MV_PROTECT)){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,5,4);
}
if ((tplayer->mv_flags[i]&MV_STORMCLOAK)!=(mv_flags[i2]&MV_STORMCLOAK)){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,6,4);
}
if ((tplayer->mv_flags[i]&MV_TYPING)!=(mv_flags[i2]&MV_TYPING)){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,7,4);
}
if (tplayer->mv_hpmp[i]!=mv_hpmp[i2]){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,8,4);
BITSadd(t,&bitsi,mv_hpmp[i2],8);
}
if (tplayer->mv_ktar[i]!=mv_ktar[i2]){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,9,4);
BITSadd(t,&bitsi,mv_ktar[i2],4);
}
if ((tplayer->mv_flags[i]&MV_SPEAKING)!=(mv_flags[i2]&MV_SPEAKING)){
if (i3==0){i3=1; BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,i,z3);}else{BITSadd(t,&bitsi,1,1);}
BITSadd(t,&bitsi,10,4);
}
if (i3){
BITSadd(t,&bitsi,0,1);
sceneupdaterequired=1;
tplayer->mv_flags[i]=mv_flags[i2];
tplayer->mv_hpmp[i]=mv_hpmp[i2];
tplayer->mv_ktar[i]=mv_ktar[i2];
tplayer->mv_more[i]=mv_more[i2];
}
}//i
BITSadd(t,&bitsi,0,1);//no more movers' states to change/toggle
//3. ADD NEW MOVER
for (i2=0;i2<mv_i;i2++){
if (mv_new[i2]==0){
sceneupdaterequired=1;
z=1; BITSadd(t,&bitsi,z,1);//add a/another mover
x=mv_x[i2]-tpx+1;//0-33
y=mv_y[i2]-tpy+1;//0-25
z=y*34+x; BITSadd(t,&bitsi,z,10);//x,y offset
z=mv_type[i2]; BITSadd(t,&bitsi,z,10);//type YET TO BE OPTOMIZED
if (z==413){//silver serp
BITSadd(t,&bitsi,mv_frame[i2],4);
goto mover_add_special;
}
if (z==366){//tanglevine tendril (not core)
BITSadd(t,&bitsi,mv_frame[i2],3);
goto mover_add_special;
}
//check if direction is required (z3 is number of bits to use to send direction)
z3=2;
if (obji[sprlnk[z]].v4==3) z3=0;//"bird"
if (z==365) z3=0;//tanglevine core
if (z==374) z3=0;//hydra core
if (z==375) z3=0;//slime
if (z==391) z3=0;//farmer hoeing
if (z==415) z3=0;//raft
BITSadd(t,&bitsi,mv_dir[i2],z3);
mover_add_special:
//***STATE CHANGES***
if(mv_ktar[i2]){
BITSadd(t,&bitsi,1,1);//a/another state change/toggle is required
BITSadd(t,&bitsi,9,4);//ktar update
BITSadd(t,&bitsi,mv_ktar[i2],4);
}
if(mv_playerid[i2]){
BITSadd(t,&bitsi,1,1);//a/another state change/toggle is required
BITSadd(t,&bitsi,8,4);
BITSadd(t,&bitsi,mv_hpmp[i2],8);
BITSadd(t,&bitsi,mv_playerid[i2],32);
}
if(mv_flags[i2]&MV_LIGHTBRIGHT){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,0,4);}
if(mv_flags[i2]&MV_LIGHTGLOW){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,1,4);}
if(mv_flags[i2]&MV_INVISIBLE){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,2,4);}
if(mv_flags[i2]&MV_PARALYZE){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,3,4);}
if(mv_flags[i2]&MV_SLEEP){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,4,4);}
if(mv_flags[i2]&MV_PROTECT){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,5,4);}
if(mv_flags[i2]&MV_STORMCLOAK){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,6,4);}
if(mv_flags[i2]&MV_TYPING){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,7,4);}
if(mv_flags[i2]&MV_SPEAKING){BITSadd(t,&bitsi,1,1); BITSadd(t,&bitsi,10,4);}
//mv_more(rider type,...)
if(mv_more[i2]){
BITSadd(t,&bitsi,1,1);//a/another state change/toggle is required
BITSadd(t,&bitsi,11,4);
BITSadd(t,&bitsi,mv_more[i2],16);
}
z=0; BITSadd(t,&bitsi,z,1);//no more state changes required
//add temp mover data to client list
i=tplayer->mv_i;
tplayer->mv_x[i]=mv_x[i2];
tplayer->mv_y[i]=mv_y[i2];
tplayer->mv_type[i]=mv_type[i2];
tplayer->mv_dir[i]=mv_dir[i2];
tplayer->mv_frame[i]=mv_frame[i2];
tplayer->mv_object[i]=mv_object[i2];
tplayer->mv_flags[i]=mv_flags[i2];
tplayer->mv_hpmp[i]=mv_hpmp[i2];
tplayer->mv_playerid[i]=mv_playerid[i2];
tplayer->mv_ktar[i]=mv_ktar[i2];
tplayer->mv_more[i]=mv_more[i2];
tplayer->mv_i++;
}//mv_new[i2]==0
}//i2
z=0; BITSadd(t,&bitsi,z,1);
if (sceneupdaterequired){
t->l=bitsi>>3; if (bitsi&7) t->l++; NET_send(NETplayer,tplayer->net,t); tplayer->updatemessage=1;
}else{
tplayer->updatemessage=0;
}
}else{//tplayer->updatemessage
tplayer->updatemessage=0;
}
/*
1. remove
2.1 change
2.2 move
3. add
***1. REMOVE MOVER***
1 if =1 remove a/another mover
{
[?] index of mover to remove based on current buffer
}
***2.1 CHANGE/TOGGLE STATE***
1 if =1 change/toggle a/another mover's state
{
[?] index of mover in current buffer
a:
4 state change id
0 LIGHTBRIGHT (LIGHTGLOW assumed off)
1 LIGHTGLOW (LIGHTBRIGHT assumed off)
2 INVISIBLE
3 PARALYZE
4 SLEEP
5 PROTECT
6 STORMCLOAK
7 TYPING
8 hpmp{ 8 new hpmp byte }
9 ktar{ 4 new ktar number }
1 if =1 another state needs to be changed, goto a
}
***2.2 CHANGE FRAME (THIS IS ONLY SENT IF MOVER HAS NOT MOVED TO ANOTHER SQUARE, IN THAT CASE IT CAN BE ASSUMED)***
1 if =1 change animation frame of a/another mover
{
[?] index of mover to change the animation frame of
}
***2.3 MOVE***
1 if =1 move a/another mover
{
[?] index of mover to move in current buffer
5 number representing a special x,y offset from current location to move to
}
***3. ADD NEW MOVER***
1 if =1 add a/another mover
{
10 x,y offset to add mover
8-10 (number of bits will depend on yet to be implemented optomization) mover's object type
2 direction mover is facing
a:
1 if =1 a/another state change/toggle is required
{
4 state change id
0 LIGHTBRIGHT (LIGHTGLOW assumed off)
1 LIGHTGLOW (LIGHTBRIGHT assumed off)
2 INVISIBLE
3 PARALYZE
4 SLEEP
5 PROTECT
6 STORMCLOAK
7 TYPING
8 hpmp+playerid{ 8 new hpmp byte
32 playerid }
9 ktar{ 4 new ktar number }
goto a
}
}
*/
//flags/pointers used while comparing buffers
//unsigned long mv_last[MVLISTLAST+1];
//unsigned long mv_new[MVLISTLAST+1];
/*
if (!playerlist[tpl]->updatemessage){
static unsigned char *p,*p2;
txtNEWLEN(t,-1048576); //create 1MB buffer
p=t->d2;
*p=1; p++;
*(float*)p=btime2; p+=4;
//central object offset->x,y
if (playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
x=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]->x;
y=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]->y;
}else{
x=playerlist[tpl]->px; y=playerlist[tpl]->py;
}
//screen offset->tpx,tpy
tpx=x-15; tpy=y-11;
if (tpx<0) tpx=0; if (tpy<0) tpy=0;
if (tpx>2016) tpx=2016;
if (tpy>1000) tpy=1000;
//add tpx,tpy to message
*(unsigned short*)p=tpx; p+=2;
*(unsigned short*)p=tpy; p+=2;
if (playerlist[tpl]->xray){ //xray!
for (x2=0;x2<=65535;x2++) pfa[x2]=PFs+PFd;
}else{
pathfind2(x,y,NULL);
}
//send blank squares
//with no obstructions this routine will still send 7 bytes (equivalent to only 2 objects!)
//BUT it is optomized basic obstructions caused by buildings/caves etc.
//OLD METHOD WAS: starting type(1), number of type(2), (assume type change)number of type(2)
//NEW METHOD: number of type+type*128(1), ...
//benefit: halved bandwidth in basic/complex situations
x4=0; z4=2;
for (y=0;y<=25;y++){ for (x=0;x<=33;x++){
if (pfa[x+y*256+257]&(PFs+PFd)) z5=1; else z5=0;
if (z5!=z4){
if (z4!=2){ //not the first pass
*p=x4+z4*128; p++;
}//z4!=2
x4=0; //number of squares in a row -1
z4=z5; //type (1 or 0)
}else{
if (x4==127){
*p=127+z4*128; p++;
x4=0;
}else{
x4++;
}
}
}}//x,y
*p=x4+z4*128; p++; //save last row
//update basetiles message
//update objects message
static long updatex,updatey;
x2=0; x3=0;
p2=p; p+=2; //create 2 bytes space to set number of objects
for (y=0;y<=23;y++){ for (x=0;x<=31;x++){
updatex=tpx+x; updatey=tpy+y;
myobj=od[updatey][updatex];
nextobj: if (myobj){
if (myobj->type==416){//view redirector
if (myobj->more2){
bt[updatey][updatex]=bt[myobj->more2>>16][myobj->more2&65535]; //update basetile flags (is this best location?)
updatex=myobj->more2&65535; updatey=myobj->more2>>16;//change currect scan location
myobj=od[myobj->more2>>16][myobj->more2&65535];//change current object
goto nextobj;
}
}//view redirector
i2=myobj->type&1023; //get object identity
if (myobj->info&256){ //quest/don'tsend
if (obji[sprlnk[i2]].weight==0){
goto display_skip;
}
if (i2==73){ //moonstone
if (playerlist[tpl]->GNPCflags[4]&(1<<(myobj->type>>10))) goto display_skip;
}
if (myobj->type==(275+2*1024)){//yellow potion
if (myobj->info&256){//quest
if (playerlist[tpl]->GNPCflags[32]&myobj->more2) goto display_skip;
}//quest
}//yellow potion
if ((i2>=242)&&(i2<=249)){ //rune
if (playerlist[tpl]->GNPCflags[5]&(1<<(i2-242))) goto display_skip;
}
if ((i2>=400)&&(i2<=407)){ //map(0-7)
if (playerlist[tpl]->GNPCflags[7]&(1<<(i2-400))) goto display_skip;
}
if (i2==62){ //vortex cube
if ((myobj->x==923)&&(myobj->y==850)){
if ((playerlist[tpl]->GNPCflags[18]&1)==0) goto display_skip;
}
if ((myobj->x==1939)&&(myobj->y==57)){
if (playerlist[tpl]->GNPCflags[6]&(1<<1)) goto display_skip;
}
}
if (i2==389){ //silver tablet
if (playerlist[tpl]->GNPCflags[6]&(1<<2)) goto display_skip;
}
if (i2==390){ //silver tabletII
if (playerlist[tpl]->GNPCflags[6]&(1<<3)) goto display_skip;
}
if (i2==270){ //balloon plans
if (playerlist[tpl]->GNPCflags[6]&(1<<4)) goto display_skip;
}
if (i2==395){ //broken gargoyle lens
if (playerlist[tpl]->GNPCflags[6]&(1<<5)) goto display_skip;
}
if (i2==394){ //brit lens
if ((playerlist[tpl]->GNPCflags[18]&2)==0) goto display_skip;
}
if (i2==396){ //garg lens
if ((playerlist[tpl]->GNPCflags[18]&4)==0) goto display_skip;
}
}//quest/don't send
if (myobj==nuggetsfix){ //nuggets
if (playerlist[tpl]->online<1536) goto display_skip;
if (playerlist[tpl]->GNPCflags[6]&(1<<6)) goto display_skip;
}
if (i2==59){ //codex
if (playerlist[tpl]->GNPCflags[18]&8) goto display_skip;
}
if (i2==51){ //force field
myobj2=(object*)myobj->prev;
if (playerlist[tpl]->GNPCflags[3]&(1<<(myobj2->type>>10))) goto display_skip;
}//force field
if (i2==173){ //trap
if ((myobj->info&(1<<9))==0) goto display_skip;
}//trap
crt=NULL;
if (myobj->info&4){ //crt
crt=(creature*)myobj->more;
if (crt->flags&2) goto display_skip;
}else{//!crt
if (myobj->info&8){ //indirect crt
if (((object*)myobj->more)->info&4) crt=(creature*)((object*)myobj->more)->more;
}
}//crt
if (pfa[x+2+y*256+512]&(PFs+PFd)){
//DISPLAY DOORS ON RANGE EDGES???
//SUPPORT FOR VIEW REDIRECTORS
if (i2==334) goto display_override; //secret door
if (i2==213) goto display_override; //mousehole
if (myobj2=OBJfindlastall(updatex,updatey)){
if ((myobj2->type&1023)==301) goto display_override;
}
if (myobj2=OBJfindlastall(updatex,updatey+1)){
if ((myobj2->type&1023)==301) goto display_override;
}
if (myobj2=OBJfindlastall(updatex+1,updatey)){
if ((myobj2->type&1023)==301) goto display_override;
}
if (pfa[x+2+y*256+512+1]&(PFs+PFd)){
if (pfa[x+2+y*256+512+256]&(PFs+PFd)){
if (pfa[x+2+y*256+512+256+1]&(PFs+PFd)){
display_override:
//length from prev obj (stored extendable from 1 to 2 bytes)
if (x2<=127){
*p=x2; p++;
}else{ //>127
*p=(x2&127)+128; p++;
*p=x2>>7; p++;
}
if (myobj->info&128){//stolen item
for (z=0;z<=15;z++){
if (stolenitemwarning[z]==myobj){
if (stolenitemwarning_player[z]!=playerlist[tpl]){
*(unsigned short*)p=1023+7*1024; p+=2;
}
}//==myobj
}//z
}//stolen item
if (myobj->info&4){ //crt
if (crt->flags&8){ //paralyzed!
*(unsigned short*)p=1023+3*1024; p+=2;
}//8, paralyzed
if (playerlist[tpl]->ktar_display){
for (z=0;z<=9;z++){
if (playerlist[tpl]->ktar_wait[z]){
if ((object*)playerlist[tpl]->ktar[z]->more==myobj){
*(unsigned short*)p=1022+z*1024; p+=2;
}
}
}
}
}//crt
if (crt){ //direct or indirect crt
//sleeping?
if (crt->flags&4){
z=myobj->type&1023; z2=0;
if (z==376) z2=339+6*1024;
if (z==377) z2=339+5*1024;
if (z==378) z2=339+3*1024;
if (z==379) z2=339+2*1024;
if (z==380) z2=339+2*1024;
if (z==381) z2=339+8*1024;
if (z==382) z2=339+4*1024;
if (z==383) z2=339+8*1024;
if (z==384) z2=339+5*1024;
if (z==385) z2=339+8*1024;
if (z==386) z2=339+7*1024;
if (z==387) z2=339+3*1024;
if (z==410) z2=339+7*1024;
//monsters
if (z==370) z2=339+1*1024; //headless
if (z==371) z2=339+0*1024; //troll
if (z==424){ //cyclops
z2=340+((myobj->type>>10)&3)*1024;
if (((myobj->type>>10)&3)!=1){
if (bt[y+tpy][x+tpx]&1024) bt[y+tpy][x+tpx]-=1024; //set as blocked!
}
}
if (z2){
*(unsigned short*)p=z2; p+=2; goto type_or;
}
}//sleeping?
}//direct or indirect crt
if (myobj->info&2){
tnpc=(npc*)myobj->more;
if (tnpc->player){ //has player pointer
if (tnpc->protection){*(unsigned short*)p=1023+4*1024; p+=2;}
if (tnpc->light){
*(unsigned short*)p=1023+1*1024; p+=2;
}else{
if (tnpc->player==playerlist[tpl]){
*(unsigned short*)p=1023+2*1024; p+=2;
}//->light
}//tnpc->player
if (myobj3=tnpc->armour){
if (myobj3->type==81){ //storm cloak
*(unsigned short*)p=1023+6*1024; p+=2;
}//81
}//armour
if (obji[sprlnk[myobj->type&1023]].v4==1){ //humantype
tplayer2=(player*)tnpc->player;
if (tplayer2->party[0]==myobj){ //first player
//first player of their party
if (tplayer2->typing){
if (tplayer!=tplayer2){ //not the same party member
*(unsigned short*)p=1023+5*1024; p+=2;
}
}
*(unsigned short*)p=myobj->type+16384; //16384=extra info
if (tnpc->flags&4){ //if asleep switch to sleeping object
z=myobj->type&1023; z2=0;
//sleeping NPC schedule, but not in bed
if (z==376) z2=339+6*1024;
if (z==377) z2=339+5*1024;
if (z==378) z2=339+3*1024;
if (z==379) z2=339+2*1024;
if (z==380) z2=339+2*1024;
if (z==381) z2=339+8*1024; //2004
if (z==382) z2=339+4*1024;
if (z==383) z2=339+8*1024;
if (z==384) z2=339+5*1024;
if (z==385) z2=339+8*1024;
if (z==386) z2=339+7*1024;
if (z==387) z2=339+3*1024;
if (z==410) z2=339+7*1024;
if (z2!=0){
*(unsigned short*)p=z2+16384; //16384=extra info
}
}//asleep
if (tnpc->flags&2) *(unsigned short*)p|=32768; //invisible
p+=2;
//U6OID 4bytes vs name(10)+colour(2)+unique id for messaging
*(unsigned long*)p=tplayer2->id; p+=4;
//addhp&mp bars (uses 1 byte of code) 0-15, 0-7, 1bit stating poisioned
f=(float)tnpc->hp/(float)tnpc->hp_max; z=f*16; if (z==16) z=15;
f=(float)tnpc->mp/(float)tnpc->mp_max; z2=f*8; if (z2==8) z2=7;
z=z+(z2<<4); if (tnpc->flags&1) z+=128;
*p=z; p++;
goto type_or;
}
}
}
if (tnpc->flags&(2+4)){//2,4
*(unsigned short*)p=myobj->type;
if (tnpc->flags&4){ //if asleep switch to sleeping object
z=myobj->type&1023; z2=0;
//sleeping NPC schedule, but not in bed
if (z==376) z2=339+6*1024;
if (z==377) z2=339+5*1024;
if (z==378) z2=339+3*1024;
if (z==379) z2=339+2*1024;
if (z==380) z2=339+2*1024;
if (z==381) z2=339+8*1024; //2004
if (z==382) z2=339+4*1024;
if (z==383) z2=339+8*1024;
if (z==384) z2=339+5*1024;
if (z==385) z2=339+8*1024;
if (z==386) z2=339+7*1024;
if (z==387) z2=339+3*1024;
if (z==410) z2=339+7*1024;
if (z2!=0){
*(unsigned short*)p=z2;
}
}//asleep
if (tnpc->flags&2) *(unsigned short*)p|=32768; //invisible
p+=2;
goto type_or;
}//2,4
if (tnpc->schedule){ if (tnpc->schedule_i!=-1){ if (tnpc->schedule[tnpc->schedule_i].type==0x91){ //sleeping!
if (od[y+tpy][x+tpx]->type==163){
*(unsigned short*)p=146; p+=2; goto type_or;
}
if (od[y+tpy][x+tpx]->type==(163+6144)){
*(unsigned short*)p=146+1024; p+=2; goto type_or;
}
z=myobj->type&1023;
z2=0;
//sleeping NPC schedule, but not in bed
if (z==376) z2=339+6*1024;
if (z==377) z2=339+5*1024;
if (z==378) z2=339+3*1024;
if (z==379) z2=339+2*1024;
if (z==380) z2=339+2*1024;
if (z==381) z2=339+8*1024; //2004
if (z==382) z2=339+4*1024;
if (z==383) z2=339+8*1024;
if (z==384) z2=339+5*1024;
if (z==385) z2=339+8*1024;
if (z==386) z2=339+7*1024;
if (z==387) z2=339+3*1024;
if (z==410) z2=339+7*1024;
if (z2!=0){
*(unsigned short*)p=z2; p+=2; goto type_or;
}
}}} //sleeping!
}//->npc
*(unsigned short*)p=myobj->type;
if ((myobj->type&1023)==338) goto noflash; //blood
if ((myobj->type&1023)==317) goto noflash; //317 fire field
if ((myobj->type&1023)==318) goto noflash; //318 poison field
if ((myobj->type&1023)==319) goto noflash; //319 protection field
if ((myobj->type&1023)==320) goto noflash; //320 sleep field
if ((myobj->type&1023)==84){ //red gate flash
if (((myobj->info&112)>>4)>=2) goto flash;
goto noflash;
}
if ((myobj->info&112)==16){
flash:
*(unsigned short*)p|=32768; //flashing
}
noflash:
p+=2;
type_or:
x3++; //number of objects
x2=0;
}
}
}
}//pf2!
display_skip:
if (myobj->next!=NULL){myobj=(object*)myobj->next; goto nextobj;}
} //object exists
x2++;
}} //x,y loop
*(unsigned short*)p2=x3;
//selected partymember map position (if x==0 he is not onscreen)
if (myobj=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
*(unsigned short*)p=myobj->x; p+=2;
*(unsigned short*)p=myobj->y; p+=2;
//selected partymember type
*(unsigned short*)p=myobj->type; p+=2;
}else{
*(unsigned short*)p=0; p+=2;
*(unsigned short*)p=0; p+=2;
//selected partymember type
*(unsigned short*)p=0; p+=2;
}
*p=0; t->l=(unsigned long)p-(unsigned long)t->d2; //finish direct string access
static unsigned long chksum;
chksum=0;
for (x=5;x<t->l;x++){
chksum=chksum+1+(t->d2[x]+1)*(x+1);
}
if (chksum!=playerlist[tpl]->MESSAGEupdate_chksum){
NET_send(NETplayer,playerlist[tpl]->net,t);
playerlist[tpl]->MESSAGEupdate_chksum=chksum;
playerlist[tpl]->updatemessage=1; //a basetile+object update message was sent last "clientframe"
} //chksum!=
}else{playerlist[tpl]->updatemessage=0;} //updatemessage
*/
//2003: fix input fields
playerlist[tpl]->key2=playerlist[tpl]->key; //2003: required backup key (client and host)
playerlist[tpl]->readmessage=FALSE; //basic input not overwritten by second message
//clear some keys by default while keeping others
if (playerlist[tpl]->key&KEYmb1) playerlist[tpl]->key-=KEYmb1;
if (playerlist[tpl]->key&KEYu) playerlist[tpl]->key-=KEYu;
if (playerlist[tpl]->key&KEYl) playerlist[tpl]->key-=KEYl;
if (playerlist[tpl]->key&KEYmbclick) playerlist[tpl]->key-=KEYmbclick;
if (sfbuffersend){
//create SF message
// send sfx message
//[2]how many sfx
//[sfx2]
//...
txtset(mess1,"");
txtset(t,"?");
txtset(t2,"??");
txtset(t3,"????");
txtadd(mess1,t2); //<-must be updated later
i=0;
if (playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
x=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]->x;
y=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]->y;
}else{
x=playerlist[tpl]->px; y=playerlist[tpl]->py;
}
//tpx=x-15; tpy=y-11;
//if (tpx<0) tpx=0; if (tpy<0) tpy=0;
//if (tpx>2016) tpx=2016;
//if (tpy>1000) tpy=1000;
getscreenoffset(x,y,&tpx,&tpy);
tpx>>=3; tpy>>=3;
for (y=tpy;y<=tpy+3;y++){
for (x=tpx;x<=tpx+4;x++){
sfxglobal:
if (sfi[y][x]){
i3=sfi[y][x];
addsf:
t2->d2[0]=sf[i3].type&255;
t2->d2[1]=sf[i3].type>>8; txtadd(mess1,t2);
t2->d2[0]=sf[i3].x&255;
t2->d2[1]=sf[i3].x>>8; txtadd(mess1,t2);
t2->d2[0]=sf[i3].y&255;
t2->d2[1]=sf[i3].y>>8; txtadd(mess1,t2);
static txt* dbgt3;
if (sf[i3].type==SF_TXT_PORTRAIT){
dbgt3=(txt*)sf[i3].p; //length of appended text message
//dbgt3=(txt*)&dbgt3;
//exit (dbgt3->l);
t2->ds[0]=dbgt3->l&0xFFFF; txtadd(mess1,t2);
t2->ds[0]=0; txtadd(mess1,t2); //unused
}else{
t2->d2[0]=sf[i3].x2&255;
t2->d2[1]=sf[i3].x2>>8; txtadd(mess1,t2);
t2->d2[0]=sf[i3].y2&255;
t2->d2[1]=sf[i3].y2>>8; txtadd(mess1,t2);
}
t2->d2[0]=sf[i3].more&255;
t2->d2[1]=sf[i3].more>>8; txtadd(mess1,t2);
t2->d2[0]=sf[i3].wait2[0];
t2->d2[1]=sf[i3].wait2[1]; txtadd(mess1,t2);
t2->d2[0]=sf[i3].wait2[2];
t2->d2[1]=sf[i3].wait2[3]; txtadd(mess1,t2);
if (sf[i3].type==SF_TXT_PORTRAIT){
txtadd(mess1,dbgt3); //append message
}
i++; //nsf
if (sf[i3].next) {i3=sf[i3].next; goto addsf;}
} //sfi!=NULL
if ((x==(2047>>3))&&(y==(1023>>3))) goto sfxglobal2;
if ((y==tpy+3)&&(x==tpx+4)) {x=2047>>3; y=1023>>3; goto sfxglobal;}
}} //x,y
sfxglobal2:
mess1->d2[0]=i&255; mess1->d2[1]=i>>8; //set number of entries
//if (playerlist[tpl]->net!=NULL){
if (mess1->l>2){ //avoid sending a NULL buffer
txtset(t,"?");
t->d2[0]=MSG_SF; //update SF
txtadd(t,mess1);
NET_send(NETplayer,playerlist[tpl]->net,t);
}
}//sfbuffersend
}//net connection
}//current player
idle_skip:;
} //tpl loop
if (sfbuffersend){
//clear sf buffer
sfn=0;//NULL sf pointer (0 is never used)
for (y=0;y<=255;y++){ for (x=0;x<=255;x++){ //clear sf buffer
if (i3=sfi[y][x]){
if (sf[i3].type==SF_TXT_PORTRAIT) free((txt*)sf[i3].p); //free txt
sfi[y][x]=0;
}
}}
sfbuffersend=0;
}//sfbuffersend
//sockets: add new client
if (newsocket!=INVALID_SOCKET){
//static unsigned char socket1taken=1;//changes to 2 once socket1 is taken
for (i=1;i<=socketclientlast;i++){
if (socketclient[i]==INVALID_SOCKET){goto free_socketclient;}
}
socketclientlast++; i=socketclientlast;
free_socketclient:
//if (i==1) socket1taken=2;
socketclient[i]=newsocket;
socketclient_ip[i]=newsocket_ip;
//(re)init info
socketclient_packetsize[i]=0;
socketclient_verified[i]=0;
socket_timeout[i]=0;
socket_disconnect[i]=0;
if (socketclient_si[i]){//reinit thread info
/*
unsigned short i;//u6o socket connection array index
OK txt *d[256];//array of txt*s
OK unsigned char next;
OK unsigned char nextfree;
//other variables for temp use?
? long x4,x2,y2;
txt *t;
unsigned char exit_thread;
unsigned long thread_id;
*/
for (i2=0;i2<=255;i2++){ txtNEWLEN(socketclient_si[i]->d[i2],0); txtNEWLEN(socketclient_ri[i]->d[i2],0);}
socketclient_si[i]->next=0; socketclient_si[i]->nextfree=0;
socketclient_ri[i]->next=0; socketclient_ri[i]->nextfree=0;
socketclient_si[i]->i=newsocket; socketclient_ri[i]->i=newsocket;
socketclient_si[i]->exit_thread=0; socketclient_ri[i]->exit_thread=0;
socketclient_ri[i]->t->l=0; socketclient_ri[i]->t->d2[0]=0;
}else{//init thread info
socketclient_si[i]=(sockets_info*)malloc(sizeof(sockets_info)); socketclient_ri[i]=(sockets_info*)malloc(sizeof(sockets_info));
ZeroMemory(socketclient_si[i],sizeof(sockets_info)); ZeroMemory(socketclient_ri[i],sizeof(sockets_info));
socketclient_si[i]->i=newsocket; socketclient_ri[i]->i=newsocket;
for (i2=0;i2<=255;i2++){ socketclient_si[i]->d[i2]=txtnew(); socketclient_ri[i]->d[i2]=txtnew();}
socketclient_si[i]->next=0; socketclient_si[i]->nextfree=0; socketclient_ri[i]->next=0; socketclient_ri[i]->nextfree=0;
socketclient_ri[i]->t=txtnew(); txtNEWLEN(socketclient_ri[i]->t,-65536);
socketclient_ri[i]->t->l=0; socketclient_ri[i]->t->d2[0]=0;
}
//COULD THIS BE THE BUG? IT DOESN'T CREATE A SEND SOCKET FOR I=1
//if (i!=1){
CreateThread(NULL,0,sockets_send,(void*)i,0,(unsigned long*)&socketclient_si[i]->thread_id);
//}else{
//socketclient_si[i]->thread_id=0;
//}
CreateThread(NULL,0,sockets_receive,(void*)i,0,(unsigned long*)&socketclient_ri[i]->thread_id);
newsocket=INVALID_SOCKET;
}
static unsigned long tnet;
nextclientmessage:
x3=0;//message available flag
for (i=1;i<=socketclientlast;i++){ if (socketclient[i]!=INVALID_SOCKET){
//if socket has not sent any info (including keep-alive messages) for 8 minutes, then it is disconnected
f=64.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
socket_timeout[i]++; if (socket_timeout[i]>=8){
if (socket_disconnect[i]==0) socket_disconnect[i]=1;
}
}
if (socket_disconnect[i]==1){
for (i2=0;i2<=playerlist_last;i2++){ if (playerlist[i2]){
if (playerlist[i2]->net==i) playerlist[i2]->net=INVALID_NET;//set ->net pointer as invalid
}}//playerlist[i2],i2
CreateThread(NULL,0,sockets_disconnect,(void*)i,0,(unsigned long*)&i2);
socket_disconnect[i]=2;//socket has been disconnected
goto socket_disconnected;
}
//net_read()
if (socketclient_ri[i]->d[socketclient_ri[i]->next]->l){ //buffered data available
socket_timeout[i]=0;
txtset(t,socketclient_ri[i]->d[socketclient_ri[i]->next]);
txtNEWLEN(socketclient_ri[i]->d[socketclient_ri[i]->next],0);
socketclient_ri[i]->next++;
x3=1; tnet=i;
goto host_gotmessage;
}//->l
}//!=INVALID_SOCKET
socket_disconnected:;
}//i
host_gotmessage:
if (x3){
if (t->d2[0]==255) goto player_add;
if (t->d2[0]==249) goto player_add; //host character!
if (t->d2[0]==246){//check if player username AND/OR character name is available
txtright(t,t->l-1);
i=t->d2[0]; txtright(t,t->l-1); txtset(t2,t); txtleft(t2,i);//user name
txtright(t,t->l-i);
i=t->d2[0]; txtright(t,t->l-1); txtset(t3,t); txtleft(t3,i);//character name
txtright(t,t->l-i);
//format names
txtset(tusername,t2);
txtset(tname,t3);
format_usernames=1;
goto format_usernames0;
format_usernames1:
format_usernames=0;
//MessageBox(NULL,tusername->d,"Ultima 6 Online",MB_OK);
//MessageBox(NULL,tname->d,"Ultima 6 Online",MB_OK);
//check if names exist in saves
i2=0;
for (i=0;i<=SAVESLOTLAST;i++){ //search save buffer for player info!
if (save_buffer[i]){
if (txtsamewithoutcase(save_username[i],tusername)){
i2=1;
}
if (txtsamewithoutcase(save_name[i],tname)){
i2=2;
}
}//save_buffer[i]
}//i
//check if names exist in currently online players
//todo!
txtsetchar(t,245); txtaddchar(t,i2);
NET_send(NETplayer,tnet,t);
goto doneclmess;
}
//KEEP ALIVE MESSAGE 251 IS POSSIBLE WITH OR WITHOUT A LOGGED IN PLAYER
//check playerlist[] for tnet
for (tpl=0;tpl<=playerlist_last;tpl++){
if (playerlist[tpl]){ //current player
if (playerlist[tpl]->net==tnet) goto foundclient;
}//current player
}
goto doneclmess; //ignore message
player_add: //add new player
//send time
txtset(t2,"?"); t2->d2[0]=32;
txtset(t3,"12345678"); t3->dd[0]=btime2;
txtadd(t2,t3);
NET_send(NETplayer,tnet,t2);
static unsigned char usetpl0;
usetpl0=0; if (t->d2[0]==249) usetpl0=1;
txtset(t5,t); //t5<-t
txtright(t5,t5->l-1);
if (t5->ds[0]!=U6O_VERSION){ //version 5.5 check
txtset(t,"?"); t->d2[0]=254; NET_send(NETplayer,tnet,t); //incorrect version
txtset(t,"Add_Player->Failed:Incorrect_Version"); LOGadd(t);
goto doneclmess;
}
txtright(t5,t5->l-2);
y9=t5->d2[0];//pw encryption
txtright(t5,t5->l-1);
//get setup message info
x=t5->d2[0]; txtright(t5,t5->l-1); txtNEWLEN(tname,x); memcpy(tname->d2,t5->d2,x); txtright(t5,t5->l-x); //name
tmale_female=t5->d2[0]; txtright(t5,t5->l-1); if (tmale_female>1) tmale_female=1;
tport=194; x=t5->ds[0]; if ((x>=0)&&(x<=13)) tport=194+x; txtright(t5,t5->l-2);
ttype=410; x=t5->d2[0]; if ((x>0)&&(x<=12)) ttype=375+x; txtright(t5,t5->l-1);
txtset(t6,t5); txtleft(t6,28); txtright(t5,t5->l-28); //t6<-virtue answers
x=t5->d2[0]; txtright(t5,t5->l-1); txtNEWLEN(tusername,x); memcpy(tusername->d2,t5->d2,x); txtright(t5,t5->l-x); txtucase(tusername); //user_name
x=t5->d2[0]; txtright(t5,t5->l-1); txtNEWLEN(tuserpassword,x); memcpy(tuserpassword->d2,t5->d2,x); txtright(t5,t5->l-x); //user_password
/*if (y9==0) {
txtucase(tuserpassword); //user_password
}*/
tcreatecharacter=t5->d2[0];
txtright(t5,t5->l-1);
x=t5->d2[0]; txtright(t5,t5->l-1); txtNEWLEN(tnewuserpassword,x); memcpy(tnewuserpassword->d2,t5->d2,x); txtright(t5,t5->l-x); //new_user_password
/*if (y9==0) {
txtucase(tnewuserpassword); //new_user_password
}*/
tcustomportrait_upload=0;
tnamecolour=0;
getsetupmessageinfo_more:
if (t5->l){//... (more info)
if (t5->d2[0]==1){//upload character portrait
tcustomportrait_upload=1; txtright(t5,t5->l-1);
memcpy(&tcustomportrait,t5->d,7168); txtright(t5,t5->l-7168);
goto getsetupmessageinfo_more;
}
if (t5->d2[0]==2){ txtright(t5,t5->l-1);//u6o_namecolour
tnamecolour=t5->dl[0]&0xFFFFFF; txtright(t5,t5->l-3);
goto getsetupmessageinfo_more;
}//u6o_namecolour
if (u6o_namecolour){
txtaddchar(t,2);
txtaddshort(t,u6o_namecolour&65535); txtaddchar(t,(u6o_namecolour>>16)&255);
}//u6o_namecolour
}//t5->l
//autoformat: name, username, password, newuserpassword (all temp)
format_usernames0:
//name
txtset(t5,tname);
autoformat_name_cull2:
for (i3=0;i3<t5->l;i3++){
x=t5->d2[i3];
x2=0; //cull?
if (x<48) x2=1;
if ((x>57)&&(x<65)) x2=1;
if ((x>90)&&(x<97)) x2=1;
if (x>122) x2=1;
if ((x==45)&&(t5->d2[i3+1]!=45)) x2=0; //-
if ((x==39)&&(t5->d2[i3+1]!=39)) x2=0; //'
if ((x==46)&&(t5->d2[i3+1]!=46)) x2=0; //.
if (x==95){t5->d2[i3]=32; x=32; x2=0; goto autoformat_name_cull2;} //_ to space
if ((x==32)&&(t5->d2[i3+1]!=32)){
if (i3&&(i3!=(t5->l-1))) x2=0;
}
if (x2){
txtset(t6,t5); txtright(t6,t5->l-i3-1);
txtleft(t5,i3); txtadd(t5,t6);
goto autoformat_name_cull2;
}
}
if (t5->l>16) txtleft(t5,16);
txtset(tname,t5);
//username
txtset(t5,tusername);
txtucase(t5);
autoformat_username_cull2:
for (i3=0;i3<t5->l;i3++){
x=t5->d2[i3];
x2=0; //cull?
if (x<48) x2=1;
if (x>90) x2=1;
if ((x>57)&&(x<65)) x2=1;
if (x2){
txtset(t6,t5); txtright(t6,t5->l-i3-1);
txtleft(t5,i3); txtadd(t5,t6);
goto autoformat_username_cull2;
}
}
if (t5->l>16) txtleft(t5,16);
txtset(tusername,t5);
if (format_usernames) goto format_usernames1;
//password
if (y9==SHA2_ENCRYPTION) {
//add some salt and hash it again for save file
txtset(t9,tusername);
txtadd(t9,tuserpassword);
if (txtsame(tnewuserpassword,tuserpassword)) txtset(tnewuserpassword,"");
SHA2(t9,tuserpassword);
txtset(t,"UNKNOWN"); SHA2(t,t2); if (txtsame(tnewuserpassword,t2)) txtset(tnewuserpassword,"");
if(tnewuserpassword->l){
txtset(t9,tusername);
txtadd(t9,tnewuserpassword);
SHA2(t9,tnewuserpassword);
}
}
else {
txtset(t5,tuserpassword);
if (PW_ENCRYPTION==SHA2_ENCRYPTION) {//encrypt the old password and set as new pw
SHA2(tuserpassword,tnewuserpassword);
txtset(t9,tusername);
txtadd(t9,tnewuserpassword);
SHA2(t9,tnewuserpassword);
}
txtucase(t5);
autoformat_password_cull2:
for (i3=0;i3<t5->l;i3++){
x=t5->d2[i3];
x2=0; //cull?
if (x<48) x2=1;
if (x>90) x2=1;
if ((x>57)&&(x<65)) x2=1;
if (x2){
txtset(t6,t5); txtright(t6,t5->l-i3-1);
txtleft(t5,i3); txtadd(t5,t6);
goto autoformat_password_cull2;
}
}
if (t5->l>16) txtleft(t5,16);
txtset(tuserpassword,t5);
//new password
txtset(t5,tnewuserpassword);
txtucase(t5);
autoformat_password_cull4:
for (i3=0;i3<t5->l;i3++){
x=t5->d2[i3];
x2=0; //cull?
if (x<48) x2=1;
if (x>90) x2=1;
if ((x>57)&&(x<65)) x2=1;
if (x2){
txtset(t6,t5); txtright(t6,t5->l-i3-1);
txtleft(t5,i3); txtadd(t5,t6);
goto autoformat_password_cull4;
}
}
if (t5->l>16) txtleft(t5,16);
txtset(tnewuserpassword,t5);
//really a new password?
txtset(t,"UNKNOWN"); if (txtsame(tnewuserpassword,t)) txtset(tnewuserpassword,"");
if (txtsame(tnewuserpassword,tuserpassword)) txtset(tnewuserpassword,"");
if (PW_ENCRYPTION==SHA2_ENCRYPTION) {//encrypt the old password and set as new pw
SHA2(t9,tnewuserpassword);
}
}
//NULL username, password or character-name?
x=0;
if (tusername->l==0) x=1;
if (tuserpassword->l==0) x=1;
if (tname->l==0) x=1;
//"UNKNOWN" username or password?
if (txtsame(tusername,t)) x=1;
if (txtsame(tuserpassword,t)) x=1;
if (x){
txtset(t,"??"); t->d2[0]=250; t->d2[1]=2; NET_send(NETplayer,tnet,t); goto doneclmess;
}
static long journeyonward_i;
if (tcreatecharacter){
//username and character-name must be unique
for (i=0;i<=SAVESLOTLAST;i++){ if (save_buffer[i]){
if (txtsame(save_username[i],tusername)){
txtset(t,"??"); t->d2[0]=250; t->d2[1]=3; NET_send(NETplayer,tnet,t); goto doneclmess;
}
txtset(t,save_name[i]); txtucase(t); txtset(t2,tname); txtucase(t2);
if (txtsame(t,t2)){
txtset(t,"??"); t->d2[0]=250; t->d2[1]=4; NET_send(NETplayer,tnet,t); goto doneclmess;
}
}}
}else{ //!tcreatecharacter
//username and password must exist
for (i=0;i<=SAVESLOTLAST;i++){ if (save_buffer[i]){
if (txtsame(save_username[i],tusername)){
if (txtsame(save_password[i],tuserpassword)) {journeyonward_i=i; goto check_username_password_ok;}
if (y9==PW_ENCRYPTION) {
txtset(t,"???"); t->d2[0]=250; t->d2[1]=6; t->d2[2]=0; NET_send(NETplayer,tnet,t); goto doneclmess; //request password without encryption (later replace with save file spesific encryption if needed)
}
else {
//journeyonward_i=i; goto check_username_password_ok; //for pw reset
txtset(t,"??"); t->d2[0]=250; t->d2[1]=5; NET_send(NETplayer,tnet,t); goto doneclmess;
}
}
}}//i,save_buffer
if (y9==PW_ENCRYPTION) {
txtset(t,"???"); t->d2[0]=250; t->d2[1]=6; t->d2[2]=0; NET_send(NETplayer,tnet,t); goto doneclmess; //request password without encryption (later replace with save file spesific encryption if needed)
}
else {
txtset(t,"??"); t->d2[0]=250; t->d2[1]=5; NET_send(NETplayer,tnet,t); goto doneclmess;
}
}//tcreatecharacter check
check_username_password_ok:
//if player is online, re-assign net pointer
if (!tcreatecharacter){
for (i=0;i<=playerlist_last;i++){
if (playerlist[i]){ //current player
if (txtsame(tusername,playerlist[i]->name)){
if (txtsame(tuserpassword,playerlist[i]->password)){
if (socket_disconnect[playerlist[i]->net]==0) socket_disconnect[playerlist[i]->net]=1;
playerlist[i]->net=tnet; //re-establish connection
for (i2=0;i2<=7;i2++){ if (playerlist[i]->party[i2]){
tnpc=(npc*)playerlist[i]->party[i2]->more; tnpc->upflags=1;
}//party
}//i2
//flush object & mover buffers
playerlist[i]->x=0;
playerlist[i]->y=0;
playerlist[i]->sobj_bufoffx=0;
playerlist[i]->sobj_bufoffy=0;
playerlist[i]->mv_i=0;
for (y=0;y<=71;y++){ for (x=0;x<=95;x++){
playerlist[i]->sobj_bufsize[x][y]=0;
playerlist[i]->sobj_tempfixed[x][y]=0;
}}
playerlist[i]->idle=0;
playerlist[i]->idle_connect=0;
goto doneclmess; //player never left!
}}//name,password
}//current player
}//i
}//!tcreatecharacter
//create player structure (using default values)
if (usetpl0){tpl=0; i=0; playerlist_last++; goto gotfreeindex;}
for (i=1;i<=playerlist_last;i++){
if (playerlist[i]==NULL){ //free index
tpl=i; goto gotfreeindex;
}//free index
}//i
playerlist_last++; tpl=playerlist_last; i=tpl; //no free index, allocate new index
gotfreeindex:
playerlist[tpl]=(player*)malloc(sizeof(player)); ZeroMemory(playerlist[tpl],sizeof(player));
playerlist[tpl]->talk_target=OBJnew();
for (x=0;x<=9;x++) playerlist[tpl]->ktar[x]=OBJnew(); //setup NULL keyboard targeting objects
playerlist[tpl]->net=tnet;
playerlist[tpl]->name=txtnew(); txtset(playerlist[tpl]->name,tusername);
playerlist[tpl]->password=txtnew(); txtset(playerlist[tpl]->password,tuserpassword);
playerlist[tpl]->newpassword=txtnew(); txtset(playerlist[tpl]->newpassword,tnewuserpassword);
playerlist[tpl]->idle=0;
playerlist[tpl]->idle_connect=0;
playerlist[tpl]->karma=100;
playerlist[tpl]->male_female=tmale_female;
playerlist[tpl]->mixer_volume=255;//assume 100% mixer volume until updated
//add player's sprite
myobj=OBJnew();
playerlist[i]->party[0]=myobj; //player<-
myobj->type=ttype; //avatar (default)
OBJadd(256+128-16,256+128+2,myobj); //place avatar on the map
//Step 3: create a NPC structure, the player's stats
tnpc=(npc*)malloc(sizeof(npc));
ZeroMemory(tnpc,sizeof(npc));
myobj->more=tnpc; myobj->info|=2; //myobj<-
//create an INVISIBLE container for player's items
myobj2=OBJnew();
myobj2->type=188; //bag (INVISIBLE)
myobj2->info|=256; //quest items OK
tnpc->items=myobj2;
tnpc->baseitem=myobj2;
tnpc->port=tport;
tnpc->order=0;
tnpc->follow=playerlist[tpl]->party[0];
tnpc->name=txtnew();
tnpc->player=playerlist[tpl];
tnpc->upflags=1;
if (tcreatecharacter) goto save_createcharacter;
i=journeyonward_i;
txtset(t2,".\\save\\"); txtnumint(t,i); txtadd(t,".sav"); txtadd(t2,t);
tfh=open2(t2,OF_READWRITE|OF_SHARE_COMPAT); txtNEWLEN(t4,lof(tfh)); get(tfh,t4->d2,t4->l); close(tfh);
save_version=t4->ds[0];
if (save_version==3){ //DECRYPT3.0
decrypt(t4);
save_version=2;
}
txtright(t4,t4->l-2);
if (save_version==5){
txtright(t4,t4->l-1);//for now do nothing with pw encrypt version will be useful later if some one implements a new encryption
}
x=t4->d2[0]; txtright(t4,t4->l-1-x); //skip name (already known)
x=t4->d2[0]; txtright(t4,t4->l-1-x); //skip password (already known)
x=t4->ds[0]; txtright(t4,t4->l-2); y=t4->ds[0]; txtright(t4,t4->l-2);
OBJremove(playerlist[tpl]->party[0]); OBJadd(x,y,playerlist[tpl]->party[0]);
playerlist[tpl]->male_female=t4->d2[0]; txtright(t4,t4->l-1);
memcpy(&playerlist[tpl]->NPCflags,t4->d,256*4); txtright(t4,t4->l-(256*4));
memcpy(&playerlist[tpl]->GNPCflags,t4->d,256*4); txtright(t4,t4->l-(256*4));
playerlist[tpl]->karma=t4->df[0]; txtright(t4,t4->l-4);
f=playerlist[tpl]->karma; stealing_MESSAGE=FALSE;
if (save_version==1){
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; playerlist[tpl]->mobj=myobj2;} txtright(t4,t4->l-8); //->mobj
}
myobj6=NULL; //set to current deed!
static object *iskiff[256],*ideed[256];
static short iskiffx,ideedx;
iskiffx=-1; ideedx=-1;
static object *npchorsepapers[8];
ZeroMemory(&npchorsepapers,sizeof(npchorsepapers));
addnewpartymember:
//KNOWN BUGS: multiple primary boats!, iskiff arrays(position), ->conversation is incorrect!
//NPC
//myobj,tnpc
myobj->type=t4->ds[0]; txtright(t4,t4->l-2);
x=t4->d2[0]; txtright(t4,t4->l-1); txtset(t,t4); txtleft(t,x); txtright(t4,t4->l-x); txtset(tnpc->name,t);
if (playerlist[tpl]->party[1]==NULL){ //primary player
txtset(tnpc->name,save_name[i]); //autoname edit
txtset(tname,tnpc->name); //for ignore.txt???
}
//Kalour FIX
#ifdef CLIENT
txtset(t,"Kalour");
if (txtsame(t,tnpc->name)){
OBJremove(playerlist[tpl]->party[0]); OBJadd(387,372,playerlist[tpl]->party[0]); //in swamp
}
#endif
tnpc->port=t4->ds[0]; txtright(t4,t4->l-2);
if (playerlist[tpl]->party[1]){ //if there is second party member then this is not the primary player!
tnpc->converse=201;
tnpc->schedule=&schedule2[0][0];
tnpc->schedule_i=-1; //unknown
tnpc->order=1; //schedule
}
tnpc->hp=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->hp_max=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->mp=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->mp_max=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->s=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->d=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->i=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->exp=t4->dl[0]; txtright(t4,t4->l-4);
tnpc->lev=t4->ds[0]; txtright(t4,t4->l-2);
tnpc->flags=t4->d2[0]; txtright(t4,t4->l-1);
tnpc->wt=0; tnpc->wt_max=tnpc->s*4*100; tnpc->wt2=0; tnpc->wt2_max=tnpc->s*50;
if (playerlist[tpl]->party[1]){//if set, not primary partymember
tnpc->mp_max=get_mp_max(tnpc->i);
//tnpc->wt_max/=2;//halve wt_max for non-primary partymember
tnpc->wt_max=tnpc->s*3*100;
}else{
tnpc->mp_max=tnpc->i*2;
}
if (save_version==1) goto sv1_objects;
//***HUGE VERSION DIFFERENCES AHEAD!***
/*
create an array to align contain object pointers
extract objects from string (pointers will come first)
*/
static object *sv2o[16384];
static unsigned long sv2op[10];
sv2op[0]=t4->dl[0];
sv2op[1]=t4->dl[1];
sv2op[2]=t4->dl[2];
sv2op[3]=t4->dl[3];
sv2op[4]=t4->dl[4];
sv2op[5]=t4->dl[5];
sv2op[6]=t4->dl[6];
sv2op[7]=t4->dl[7];
sv2op[8]=t4->dl[8];
//txtnumint(t5,t4->dl[8]); txtadd(t5,":inv index"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
sv2op[9]=t4->dl[9];
//txtnumint(t5,t4->dl[9]); txtadd(t5,":mobj index"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
txtright(t4,t4->l-10*4);
/*-7168
txtset(t2,"418.BIN");
tfh=open2(t2,OF_READWRITE|OF_SHARE_COMPAT|OF_CREATE);
put(tfh,t4->d2,t4->l);
close(tfh);
exit2(4);
*/
housestoragerestore0:
//create objects (being careful of object->next & object->prev)
x=0; //first item in set
x2=-1; //index
sv2nextitem:
if (t4->dl[0]!=0){
myobj2=OBJnew();
myobj2->type=t4->ds[0];
myobj2->info=t4->ds[1];
x2++; sv2o[x2]=myobj2;
if (housestoragerestore==0){
if ((x2<(sv2op[9]-1))||(sv2op[9]==0)) stealing(playerlist[tpl],myobj2); //mobj won't be classed as being stolen
}
myobj2->more2=t4->dl[1];
//if (housestoragerestore){
//txtnumint(t5,myobj2->type); txtadd(t5,":type"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
//txtnumint(t5,myobj2->more2); txtadd(t5,":more2"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
//}
//txtnumint(t5,myobj2->type&1023);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
//GPF
if (x){ //link it to prev item
myobj2->prev=sv2o[x2-1];
sv2o[x2-1]->next=myobj2;
//txtset(t5,"linked to prev item"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
}
myobj3=myobj2;
if (myobj3->type==448){//horse papers (load)
/*
myobj2=(object*)OBJlist_list[y6]->more;
if (myobj2->x){//horse is not being ridden
t2->dl[0]=myobj2->x+myobj2->y*2048;//use as few bits as possible(21 bits total)
}else{//horse is being ridden by a partymember
t2->dl[0]=0;
//scan to detect which partymember
for(z3=0;z3<7;z3++){
if (myobj3=playerlist[tpl]->party[z3]){
tnpc3=(npc*)myobj3->more;
if (tnpc3->horse==myobj2){
t2->dl[0]=z3;
}//tnpc3->horse==myobj2
}//party[z3]
}//z3
}//myobj2->x
*/
z2=myobj3->more2&2097151;
//2097151=111111111111111111111b (21bits in binary)
//static long hc=0;
//hc++;
//if (hc==4) exit(z2);
//if (z2!=903451) if (z2!=0) exit(z2);
//t->d2[t->l-1]&=225;//11100001b
//t->d2[t->l-1]+=(z4<<1);//npc#
//((myobj3->info>>9)&15)
//oldsave patch
if (z2<=7){
npchorsepapers[z2]=myobj3;
goto oldsave_horse;
}
if (((myobj3->info>>9)&15)==8){
//create horse and set deed to point to horse
movernew(430,z2&2047,z2>>11,MOVERNEW_FLAG_NORESPAWN);
((creature*)MOVERNEW_OBJECT->more)->flags|=128;
((creature*)MOVERNEW_OBJECT->more)->al=0;
((creature*)MOVERNEW_OBJECT->more)->respawn_y=tpl;
((creature*)MOVERNEW_OBJECT->more)->respawn_x=(myobj3->more2>>21)&255;
OBJmove_allow=TRUE;
if (((myobj3->more2>>29)&3)==1){
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x-1,MOVERNEW_OBJECT->y);
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x+1,MOVERNEW_OBJECT->y);
}
if (((myobj3->more2>>29)&3)==2){
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x,MOVERNEW_OBJECT->y-1);
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x,MOVERNEW_OBJECT->y+1);
}
if (((myobj3->more2>>29)&3)==3){
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x+1,MOVERNEW_OBJECT->y);
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x-1,MOVERNEW_OBJECT->y);
}
OBJmove_allow=FALSE;
myobj3->more=MOVERNEW_OBJECT;
//If horse is inside a house evict it
x7=MOVERNEW_OBJECT->x; y7=MOVERNEW_OBJECT->y;
x6=housecheck(x7,y7);
if(x6) {
if (houseowner(playerlist[tpl],x6)) goto houseboundrycheck_horse0;
//move horse to entrance
OBJmove_allow=TRUE;
OBJmove2(MOVERNEW_OBJECT,houseentrancex[x6],houseentrancey[x6]);
OBJmove_allow=FALSE;
goto houseboundrycheck_horse0;
}
houseboundrycheck_horse0:;
//remove horse rear end!
//OBJremove((object*)((creature*)MOVERNEW_OBJECT->more)->more);
}else{
//set horse as being ridden
//t->d2[t->l-1]&=225;//11100001b
//t->d2[t->l-1]+=(z4<<1);//npc#
//((myobj3->info>>9)&15)
if (npchorsepapers[((myobj3->info>>9)&15)]) exit (576);
npchorsepapers[((myobj3->info>>9)&15)]=myobj3;
}
}//horse papers (load)
oldsave_horse:
if ((myobj3->type&1023)==414){//skiff
iskiffx++; iskiff[iskiffx]=myobj3;
}
if (myobj3->type==149){//deed
//ok lets add this ship if it's not current ship
if (myobj3->more2==NULL){ //inventory deed!
ideedx++; ideed[ideedx]=myobj3;
goto ideed_done;
}
if (myobj3->more2!=0xFFFFFFFF){
//create ship/skiff!
if (myobj3->info&(1<<9)){
//skiff
myobj5=OBJnew(); myobj5->type=414; OBJadd(myobj3->more2&65535,myobj3->more2>>16,myobj5);
myobj3->more=(object*)myobj5;
}else{
//ship
myobj5=OBJnew(); myobj5->type=412+9*1024; OBJadd(myobj3->more2&65535,myobj3->more2>>16,myobj5);
static mlobj *mmyobj; //array size varies
mmyobj=(mlobj*)malloc(sizeof(object*)*5);
myobj5->more=mmyobj;
myobj=OBJnew(); mmyobj->obj[0]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[1]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[2]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[3]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[4]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj3->more=myobj5; //deed->ship
OBJmove_allow=TRUE;
OBJmove2(myobj5,myobj5->x,myobj5->y+1);
OBJmove2(myobj5,myobj5->x,myobj5->y-1);
OBJmove_allow=FALSE;
myobj3->more=(object*)myobj5;
}
}else{
myobj6=myobj3;} //set as current deed
}//149
ideed_done:
x=1;
txtright(t4,t4->l-8); //remove item
goto sv2nextitem;
}else{ //==0
//txtset(t5,"break"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
if (t4->dl[1]!=0) {x=0; txtright(t4,t4->l-4); goto sv2nextitem;} //remove 0
txtright(t4,t4->l-4); //remove last 0
txtright(t4,t4->l-4); //remove last 0
//txtset(t5,"final break"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
}
//txtset(t5,"extraction finished"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
//but what about container links?
for (x=0;x<=x2;x++){
if (obji[sprlnk[sv2o[x]->type&1023]].flags&1024){ //container
if (sv2o[x]->type==57) playerlist[tpl]->GNPCflags[30]=1; //spellbook exists?
if (sv2o[x]->more2){
myobj2=sv2o[sv2o[x]->more2-1];
sv2o[x]->more=myobj2;
myobj2->prev=sv2o[x]; //not sure if this is required but hey!
}//->more2
}//multiple
}//x
if (housestoragerestore) goto housestoragerestore1;
if (sv2op[0]) tnpc->helm=sv2o[sv2op[0]-1];
if (sv2op[1]) tnpc->wep_right=sv2o[sv2op[1]-1];
if (sv2op[2]) tnpc->wep_left=sv2o[sv2op[2]-1];
if (sv2op[3]) tnpc->armour=sv2o[sv2op[3]-1];
if (sv2op[4]) tnpc->boots=sv2o[sv2op[4]-1];
if (sv2op[5]) tnpc->neck=sv2o[sv2op[5]-1];
if (sv2op[6]) tnpc->ring_right=sv2o[sv2op[6]-1];
if (sv2op[7]) tnpc->ring_left=sv2o[sv2op[7]-1];
if (sv2op[8]){
/* tnpc->items was already set before !! and the bag item was never removed so It caused mem leak */
OBJremove(tnpc->items); OBJrelease(tnpc->items);
tnpc->items=sv2o[sv2op[8]-1]; //includes the bag!
tnpc->baseitem=tnpc->items;
}
if (playerlist[tpl]->party[1]==NULL){
if (sv2op[9]) playerlist[tpl]->mobj=sv2o[sv2op[9]-1];
}
if (playerlist[tpl]->GNPCflags[252]){
playerlist[tpl]->GNPCflags[252]--;
//create a new NPC
x8=1;
findemptyparty: if (playerlist[tpl]->party[x8]) {x8++; goto findemptyparty;}
myobj=OBJnew();
playerlist[tpl]->party[x8]=myobj; //player<-
tnpc=(npc*)malloc(sizeof(npc));
ZeroMemory(tnpc,sizeof(npc));
myobj->more=tnpc; myobj->info|=2; //myobj<-
//create an INVISIBLE container for player's items
myobj2=OBJnew();
myobj2->type=188; //bag (INVISIBLE)
tnpc->items=myobj2;
tnpc->baseitem=myobj2;
tnpc->order=1;
tnpc->follow=playerlist[tpl]->party[0];
tnpc->name=txtnew();
tnpc->player=playerlist[tpl];
tnpc->upflags=1;
OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj);
//txtnumint(t5,0); txtadd(t5,":objadd"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
goto addnewpartymember;
}
//txtnumint(t5,t4->ds[0]); txtadd(t5,":firstobj"); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
//28 house number (not valid if player has been evicted!)
//29 number of house storage positions saved
static unsigned char housestoragerestorei,housechest;
housechest=0;
if (playerlist[tpl]->GNPCflags[28]){
//MessageBox(NULL,"HOUSESTORAGECHECK: gflags say still a house owner","Ultima 6 Online",MB_OK);
if (houseowner(playerlist[tpl],playerlist[tpl]->GNPCflags[28])==0){
//player no longer owns house registered in player structure
housechest=1;
playerlist[tpl]->GNPCflags[28]=0;
}
}
for (housestoragerestorei=0;housestoragerestorei<playerlist[tpl]->GNPCflags[29];housestoragerestorei++){
//housestoragerestorei=0;
if (t4->dl[0]){
housestoragerestore=1; goto housestoragerestore0;
housestoragerestore1: housestoragerestore=0;
myobj2=sv2o[0];
if (housechest==0){
housestoragerestore2:
myobj3=(object*)myobj2->next;
if (obji[sprlnk[myobj2->type&1023]].weight){//FIX for red gate/balloon and other issues
OBJadd(housestoragex[playerlist[tpl]->GNPCflags[28]][housestoragerestorei],housestoragey[playerlist[tpl]->GNPCflags[28]][housestoragerestorei],myobj2);
}
if (myobj3) {myobj2=myobj3; goto housestoragerestore2;}
}else{
//put items in a chest and
myobj3=OBJnew(); myobj3->type=98+1024; myobj3->more=myobj2; myobj2->prev=myobj3;
tnpc3=(npc*)playerlist[tpl]->party[0]->more;
additemroot(tnpc3,myobj3);
}//==0
}else{
txtright(t4,t4->l-4);
}
}
//housestoragerestore1:
//for (x2=0;x2<playerlist[tpl]->GNPCflags[29];x2++){
//myobj=(object*)od[housestoragey[playerlist[tpl]->GNPCflags[28]][x2]][housestoragex[playerlist[tpl]->GNPCflags[28]][x2]]->next;
//x5=0;
//housestorageadd=1; goto housestorageadd0;
//housestorageadd1: housestorageadd=0;
//}
//fix inventory skiff deeds
for (x=0;x<=iskiffx;x++){
if (ideedx>=x){
iskiff[x]->more=ideed[x];
ideed[x]->more=iskiff[x];
}else{
iskiff[x]->info|=(1<<9); //free skiff!
iskiff[x]->more2=NULL; //null deed
}
}
for (x=0;x<=ideedx;x++){
if (iskiffx<x){
OBJremove(ideed[x]); //remove invalid deed!
}
}
goto sv2_done;
sv1_objects:
//equipment
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->helm=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->wep_right=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->wep_left=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->armour=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->boots=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->neck=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->ring_right=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
if (t4->ds[0]) {myobj2=OBJnew(); myobj2->type=t4->ds[0]; myobj2->info=t4->ds[1]; myobj2->more2=t4->dl[1]; tnpc->ring_left=myobj2; stealing(playerlist[tpl],myobj2);} txtright(t4,t4->l-8);
x=t4->ds[0]; txtright(t4,t4->l-2); //item n
for (x2=0;x2<x;x2++){
myobj3=OBJnew(); myobj3->type=t4->ds[0]; myobj3->info=t4->ds[1]; myobj3->more2=t4->dl[1];
//PATCH! 1.0
if (myobj3->type==64){ //key A
if (myobj3->more2&32768) myobj3->more2-=32768;
}
stealing(playerlist[tpl],myobj3);
additem(tnpc,myobj3);
if (myobj3->type==149){//deed
//ok lets add this ship if it's not current ship
if (myobj3->more2!=0xFFFFFFFF){
//create ship/skiff!
if (myobj3->info&(1<<9)){
//skiff
myobj5=OBJnew(); myobj5->type=414; OBJadd(myobj3->more2&65535,myobj3->more2>>16,myobj5);
myobj3->more=(object*)myobj5;
}else{
//ship
myobj5=OBJnew(); myobj5->type=412+9*1024; OBJadd(myobj3->more2&65535,myobj3->more2>>16,myobj5);
static mlobj *mmyobj; //array size varies
mmyobj=(mlobj*)malloc(sizeof(object*)*5);
myobj5->more=mmyobj;
myobj=OBJnew(); mmyobj->obj[0]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[1]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[2]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[3]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[4]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj3->more=myobj5; //deed->ship
OBJmove_allow=TRUE;
OBJmove2(myobj5,myobj5->x,myobj5->y+1);
OBJmove2(myobj5,myobj5->x,myobj5->y-1);
OBJmove_allow=FALSE;
myobj3->more=(object*)myobj5;
}
}else{
myobj6=myobj3;} //set as current deed
}//149
txtright(t4,t4->l-8);
}
sv2_done:
playerlist[tpl]->karma=f; stealing_MESSAGE=TRUE;
//move player to front door of house if not the owner
x2=playerlist[tpl]->party[0]->x; y2=playerlist[tpl]->party[0]->y;
x=housecheck(x2,y2);
if(x) {
if (houseowner(playerlist[tpl],x)) goto houseboundrycheck0;
//trespassing! move player to entrance
for (x3=7;x3>=0;x3--){ if (playerlist[tpl]->party[x3]){
OBJremove(playerlist[tpl]->party[x3]);
OBJadd(houseentrancex[x],houseentrancey[x],playerlist[tpl]->party[x3]);
}}//x3,->party[x3]
goto houseboundrycheck0;
}//x
houseboundrycheck0:
//place selected partymembers on horses
for (x=0;x<=7;x++){
if (npchorsepapers[x]){
myobj2=playerlist[tpl]->party[x]; tnpc2=(npc*)myobj2->more;
z2=npchorsepapers[x]->more2&2097151;
if ((z2<=7)||(z2==2097151)){
movernew(430,myobj2->x,myobj2->y,MOVERNEW_FLAG_NORESPAWN); myobj=MOVERNEW_OBJECT;
}else{
movernew(430,z2&2047,z2>>11,MOVERNEW_FLAG_NORESPAWN); myobj=MOVERNEW_OBJECT;
}
((creature*)MOVERNEW_OBJECT->more)->flags|=128;
((creature*)MOVERNEW_OBJECT->more)->al=0;
((creature*)MOVERNEW_OBJECT->more)->respawn_y=tpl;
((creature*)MOVERNEW_OBJECT->more)->respawn_x=(npchorsepapers[x]->more2>>21)&255;
//remove horse rear end!
//OBJremove((object*)((creature*)MOVERNEW_OBJECT->more)->more);
OBJmove_allow=TRUE;
if (((npchorsepapers[x]->more2>>29)&3)==1){
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x-1,MOVERNEW_OBJECT->y);
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x+1,MOVERNEW_OBJECT->y);
}
if (((npchorsepapers[x]->more2>>29)&3)==2){
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x,MOVERNEW_OBJECT->y-1);
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x,MOVERNEW_OBJECT->y+1);
}
if (((npchorsepapers[x]->more2>>29)&3)==3){
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x+1,MOVERNEW_OBJECT->y);
OBJmove2(MOVERNEW_OBJECT,MOVERNEW_OBJECT->x-1,MOVERNEW_OBJECT->y);
}
OBJmove_allow=FALSE;
x7=MOVERNEW_OBJECT->x; y7=MOVERNEW_OBJECT->y; //check if the horse is inside a house
x6=housecheck(x7,y7);
if(x6) {
if (houseowner(playerlist[tpl],x6)) goto houseboundrycheck_horse1;
//move horse to entrance
OBJmove_allow=TRUE;
OBJmove2(MOVERNEW_OBJECT,houseentrancex[x6],houseentrancey[x6]);
OBJmove_allow=FALSE;
goto houseboundrycheck_horse1;
}//x
houseboundrycheck_horse1:;
npchorsepapers[x]->more=myobj;
tnpc2->originalobjtype=myobj2->type;
OBJremove(myobj2);
OBJadd(myobj->x,myobj->y,myobj2);
myobj2->type=myobj->type-430+431;
crt2=(creature*)myobj->more;
tnpc2->more=crt2->more; myobj3=(object*)crt2->more; myobj3->more=myobj2;//make rear end of horse point to partymember(myobj2)
myobj3->type=myobj3->type-430+431;
OBJremove(myobj);//remove front end of horse
tnpc2->horse=myobj;//backup pointer to front half of horse for later
}
}
//version 1+2, myobj6=pointer to deed of current ship
x=playerlist[tpl]->GNPCflags[255];
if (x){ //put player into craft (this is the really unfun bit!)
if (x==1){ //ship
//build and place skiff facing new direction
myobj3=OBJnew(); myobj3->type=412+9*1024; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj3);
static mlobj *mmyobj; //array size varies
mmyobj=(mlobj*)malloc(sizeof(object*)*5);
myobj3->more=mmyobj;
myobj=OBJnew(); mmyobj->obj[0]=myobj; myobj->info|=8; myobj->type=myobj3->type; myobj->more=(object*)myobj3; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj);
myobj=OBJnew(); mmyobj->obj[1]=myobj; myobj->info|=8; myobj->type=myobj3->type; myobj->more=(object*)myobj3; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj);
myobj=OBJnew(); mmyobj->obj[2]=myobj; myobj->info|=8; myobj->type=myobj3->type; myobj->more=(object*)myobj3; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj);
myobj=OBJnew(); mmyobj->obj[3]=myobj; myobj->info|=8; myobj->type=myobj3->type; myobj->more=(object*)myobj3; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj);
myobj=OBJnew(); mmyobj->obj[4]=myobj; myobj->info|=8; myobj->type=myobj3->type; myobj->more=(object*)myobj3; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj);
playerlist[tpl]->craft_con=(object*)myobj3->more;
myobj3->more=playerlist[tpl]->party[0]->more;
myobj3->info=playerlist[tpl]->party[0]->info;
playerlist[tpl]->craft=playerlist[tpl]->party[0];
for (x2=0;x2<=7;x2++){
if (playerlist[tpl]->party[x2]){
OBJremove(playerlist[tpl]->party[x2]);
tnpc3=(npc*)playerlist[tpl]->party[x2]->more;
if (tnpc3->horse) OBJremove((object*)tnpc3->more);
}
}
playerlist[tpl]->party[0]=myobj3;
if (myobj3->info&32768) myobj3->info-=32768; //?
OBJmove_allow=TRUE;
OBJmove2(myobj3,playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y+1);
OBJmove2(myobj3,playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y-1);
OBJmove_allow=FALSE;
if (myobj6) myobj6->more=(object*)myobj3; //allocate current deed
}//ship
if (x==2){ //skiff
//build and place skiff facing new direction
myobj3=OBJnew(); myobj3->type=414; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj3);
myobj3->more=playerlist[tpl]->party[0]->more;
myobj3->info=playerlist[tpl]->party[0]->info;
playerlist[tpl]->craft=playerlist[tpl]->party[0];
for (x2=0;x2<=7;x2++){if(playerlist[tpl]->party[x2])OBJremove(playerlist[tpl]->party[x2]);}
playerlist[tpl]->party[0]=myobj3;
if (myobj3->info&32768) myobj3->info-=32768;
if (myobj6){
myobj6->more=(object*)myobj3; //allocate current deed
}else{
myobj3->info|=(1<<9);
}
}//skiff
if (x==3){ //raft
//build and place skiff facing new direction
myobj3=OBJnew(); myobj3->type=415; OBJadd(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj3);
myobj3->more=playerlist[tpl]->party[0]->more;
myobj3->info=playerlist[tpl]->party[0]->info;
playerlist[tpl]->craft=playerlist[tpl]->party[0];
for (x2=0;x2<=7;x2++){if(playerlist[tpl]->party[x2])OBJremove(playerlist[tpl]->party[x2]);}
playerlist[tpl]->party[0]=myobj3;
if (myobj3->info&32768) myobj3->info-=32768; //?
}//raft
if (x==4){ //balloon //build balloon
myobj2=OBJnew();
//create a balloon where the avatar is standing
x=playerlist[tpl]->party[0]->x; y=playerlist[tpl]->party[0]->y;
myobj2->type=423+1024*3; OBJadd(x,y,myobj2);
static mlobj *mmyobj; //array size varies
mmyobj=(mlobj*)malloc(sizeof(object*)*3);
myobj2->more=mmyobj;
myobj=OBJnew(); mmyobj->obj[0]=myobj; //middle
myobj->type=423+0*1024; myobj->info|=8; //<-base object
OBJadd(x-1,y-1,myobj); myobj->more=myobj2;
myobj=OBJnew(); mmyobj->obj[1]=myobj; //middle
myobj->type=423+1*1024; myobj->info|=8; //<-base object
OBJadd(x,y-1,myobj); myobj->more=myobj2;
myobj=OBJnew(); mmyobj->obj[2]=myobj; //middle
myobj->type=423+2*1024; myobj->info|=8; //<-base object
OBJadd(x-1,y,myobj); myobj->more=myobj2;
//use balloon (the one we just created :)
playerlist[tpl]->craft_con=(object*)myobj2->more;
myobj2->more=playerlist[tpl]->party[0]->more;
myobj2->info=playerlist[tpl]->party[0]->info;
playerlist[tpl]->craft=playerlist[tpl]->party[0];
for (x2=0;x2<=7;x2++){if(playerlist[tpl]->party[x2])OBJremove(playerlist[tpl]->party[x2]);}
playerlist[tpl]->party[0]=myobj2;
}//x==4
}//x
tnpc=(npc*)playerlist[tpl]->party[0]->more;
if (playerlist[tpl]->GNPCflags[253]&2){//rest
playerlist[tpl]->GNPCflags[253]-=2;
x=(unsigned long)ett-playerlist[tpl]->GNPCflags[254];
if ((x>=1536)||(x<0)){ //~24min offline
for (x=0;x<=7;x++){ if (playerlist[tpl]->party[x]){
tnpc2=(npc*)playerlist[tpl]->party[x]->more;
tnpc2->hp=tnpc2->hp_max; //heal
tnpc2->mp=tnpc2->mp_max; //full mp
}}
}
}
playerlist[tpl]->GNPCflags[251]++; //251 number of times entered britannia (as at last save)
if (playerlist[tpl]->GNPCflags[19]){ //disable showing of lenses
playerlist[tpl]->GNPCflags[22]|=0xFFFFFFFF; //make all destinations available
if (playerlist[tpl]->GNPCflags[18]&2) playerlist[tpl]->GNPCflags[18]-=2;
if (playerlist[tpl]->GNPCflags[18]&4) playerlist[tpl]->GNPCflags[18]-=4;
if (playerlist[tpl]->GNPCflags[18]&16) playerlist[tpl]->GNPCflags[18]-=16; //allow engame sequence to be replayed!
//remove amulet of submission FIX
tnpc=(npc*)playerlist[tpl]->party[0]->more;
if (tnpc->neck){
if (tnpc->neck->type==76) tnpc->neck=NULL;
}
}else{
//ORBFIX: if a player was given all gate destinations incorrectly reset to 0
if (playerlist[tpl]->GNPCflags[22]==0xFFFFFFFF) playerlist[tpl]->GNPCflags[22]=0;
}//19
//duplicate inparty name fix
for (x=0;x<=6;x++){
if (playerlist[tpl]->party[x]){
tnpc2=(npc*)playerlist[tpl]->party[x]->more; txtset(t,tnpc2->name); txtucase(t); txtset(t4,tnpc2->name);
for (x2=x+1;x2<=7;x2++){
if (playerlist[tpl]->party[x2]){
tnpc2=(npc*)playerlist[tpl]->party[x2]->more; txtset(t2,tnpc2->name); txtucase(t2);
if (txtsame(t,t2)){
//we can assume that the name is not already indexed
y=2;
inpartynamefix0:
txtset(t5,t);
if (y==2) txtset(t3,"II");
if (y==3) txtset(t3,"III");
if (y==4) txtset(t3,"IV");
if (y==5) txtset(t3,"V");
if (y==6) txtset(t3,"VI");
if (y==7) txtset(t3,"VII");
if (y==8) txtset(t3,"VIII");
txtadd(t5,t3);
for (x3=0;x3<=7;x3++){
if (playerlist[tpl]->party[x3]){
tnpc3=(npc*)playerlist[tpl]->party[x3]->more; txtset(t6,tnpc3->name); txtucase(t6);
if (txtsame(t5,t6)){ //no is unavailable
y++; goto inpartynamefix0;
}//txtsame
}//party[x3]
}//x3
if (y==2) txtadd(tnpc2->name,"II");
if (y==3) txtadd(tnpc2->name,"III");
if (y==4) txtadd(tnpc2->name,"IV");
if (y==5) txtadd(tnpc2->name,"V");
if (y==6) txtadd(tnpc2->name,"VI");
if (y==7) txtadd(tnpc2->name,"VII");
if (y==8) txtadd(tnpc2->name,"VIII");
}//txtsame
}}}}
//247&248 TEMP food values for npc 0-7, 1 byte each (only used when saving/loading)
for (x2=0;x2<=7;x2++){ if (playerlist[tpl]->party[x2]){
tnpc3=(npc*)playerlist[tpl]->party[x2]->more;
if (x2==0) x3=(playerlist[tpl]->GNPCflags[247])&255;
if (x2==1) x3=(playerlist[tpl]->GNPCflags[247]>>8)&255;
if (x2==2) x3=(playerlist[tpl]->GNPCflags[247]>>16)&255;
if (x2==3) x3=(playerlist[tpl]->GNPCflags[247]>>24)&255;
if (x2==4) x3=(playerlist[tpl]->GNPCflags[248])&255;
if (x2==5) x3=(playerlist[tpl]->GNPCflags[248]>>8)&255;
if (x2==6) x3=(playerlist[tpl]->GNPCflags[248]>>16)&255;
if (x2==7) x3=(playerlist[tpl]->GNPCflags[248]>>24)&255;
tnpc3->food=x3;
}}
//remove house key(s),...
//party inventory list(s) & m(ouse)obj(ect) (does not include equipped items!)
for (x6=0;x6<=7;x6++){ if (playerlist[tpl]->party[x6]){
tnpc3=(npc*)playerlist[tpl]->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
x5=OBJlist(playerlist[tpl]->mobj); //include mobj
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==64){ //key
if ((OBJlist_list[y6]->more2&0xFF00)==256){ //house key
OBJremove(OBJlist_list[y6]);
}
}
}//y6
//mouse object
if (playerlist[tpl]->mobj){
if (playerlist[tpl]->mobj->type==64){//key
if ((playerlist[tpl]->mobj->more2&0xFF00)==256){//house key
playerlist[tpl]->mobj=NULL;
}
}
}
//add house key
if (houseowner(playerlist[tpl],playerlist[tpl]->GNPCflags[28])){
tnpc3=(npc*)playerlist[tpl]->party[0]->more;
myobj3=OBJnew(); myobj3->type=64; myobj3->info=256; myobj3->more2=256+playerlist[tpl]->GNPCflags[28]; //house key
additemroot(tnpc3,myobj3);
}//add house key
/*
//equipped items
txtset(t,"????????");
myobj=tnpc->helm; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
myobj=tnpc->wep_right; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
myobj=tnpc->wep_left; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
myobj=tnpc->armour; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
myobj=tnpc->boots; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
myobj=tnpc->neck; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
myobj=tnpc->ring_right; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
myobj=tnpc->ring_left; t->dl[0]=0; t->dl[1]=0; if (myobj) {t->ds[0]=myobj->type; t->ds[1]=myobj->info; t->dl[1]=myobj->more2;} txtadd(t4,t);
//items?
//light?
*/
txtset(t,"Player_Entered:"); txtadd(t,tnpc->name); LOGadd(t);
//ban player
tfh=open2("ban.txt",OF_READWRITE|OF_SHARE_COMPAT); //log
ban_nextplayer:
txtfilein(t6,tfh);
if (txtsamewithoutcase(t6,tname)){
playerlist[tpl]->GNPCflags[253]|=1;
txtset(t7,"??"); t7->d2[0]=250; t7->d2[1]=8; NET_send(NETplayer,playerlist[tpl]->net,t7);
}
if (t6->l) goto ban_nextplayer;
close(tfh);
//create custom character portrait (if required)
/*
if (t5->d2[0]==1){//upload character portrait
tcustomportrait_upload=1; txtright(t5,t5->l-1);
memcpy(&tcustomportrait,t5->d,7168); txtright(t5,t5->l-7168);
goto getsetupmessageinfo_more;
}
*/
tnpc3=(npc*)playerlist[tpl]->party[0]->more;
//grant full privileges to admin players
x=0;
while (admins[x]) {
if (txtsame(tnpc3->name,admins[x])){
for (i=40;i<=47;i++) playerlist[tpl]->GNPCflags[i]=0xFFFFFFFF;
break;
}
x++;
if (x==ADMINSMAX) {break;}
}
//portraits 2.0 backup original portrait so it can be restored
if (playerlist[tpl]->GNPCflags[34]==NULL) playerlist[tpl]->GNPCflags[34]=tnpc3->port;
tnpc3->port=playerlist[tpl]->GNPCflags[34];
if (tcustomportrait_upload){
if ((playerlist[tpl]->GNPCflags[33]&2)==0){//not blocked from uploading custom portraits
if (tnpc3->lev>=3){
if (tnpc3->exp>=1000){ tnpc3->exp-=1000;
HOST_portrait_data[HOST_portrait_next]=(unsigned short*)malloc(7168);
memcpy(HOST_portrait_data[HOST_portrait_next],&tcustomportrait,7168);
HOST_portrait_loaded[HOST_portrait_next]=1;
tnpc3->port=HOST_portrait_next;
HOST_portrait_next++;
//add to database!
//get/add index
z=0;
tfh=open(".\\save\\port\\index.txt");
txtset(t2,"=");
txtset(t4,tnpc3->name); txtucase(t4);
saveportindex_loop:
txtfilein(t,tfh);
if (x=txtsearch(t,t2)){
txtset(t3,t); txtleft(t3,x-1); z=txtnum(t3);
txtright(t,t->l-x);//name
if (txtsame(t,t4)){
goto saveportindex_found;
}//txtsame(t3,t4)
goto saveportindex_loop;
}
seek(tfh,lof(tfh));
z++; txtnumint(t,z); txtadd(t,t2); txtadd(t,t4);
txtfileout(t,tfh);
saveportindex_found:
close(tfh);
//create file
static unsigned char bmpdata[54];
txtset(t,".\\save\\port\\"); txtnumint(t2,z); txtadd(t,t2); txtadd(t,".BMP");
tfh=open2(t->d,OF_READWRITE|OF_SHARE_COMPAT|OF_CREATE);
tfh2=open(".\\host\\bmpdata.bmp");
get(tfh2,&bmpdata,54);
close(tfh2);
put(tfh,&bmpdata,54);
for (x2=63;x2>=0;x2--){ for (x=0;x<56;x++){
y=tcustomportrait[x2*56+x]&31; y*=8;
put(tfh,&y,1);
y2=tcustomportrait[x2*56+x]&2016; y2>>=5; y2*=4;
put(tfh,&y2,1);
y3=tcustomportrait[x2*56+x]&63488; y3>>=11; y3*=8;
put(tfh,&y3,1);
}}
close(tfh);
playerlist[tpl]->GNPCflags[33]|=1;//check for existing custom portrait on entry
goto custromportraitload_skip;
}//tnpc3->exp>=1000
}//tnpc3->lev>=3
}//not blocked from uploading custom portraits
}//tcustomportrait_upload
//customportraitload
if (playerlist[tpl]->GNPCflags[33]&1){
tfh=open(".\\save\\port\\index.txt");
txtset(t2,"=");
txtset(t4,tnpc3->name); txtucase(t4);
custromportraitload_loop:
txtfilein(t,tfh);
if (x=txtsearch(t,t2)){
txtset(t3,t); txtleft(t3,x-1); z=txtnum(t3);
txtright(t,t->l-x);//name
if (txtsame(t,t4)){
txtset(t,".\\save\\port\\"); txtadd(t,t3); txtadd(t,".BMP");
//ADD SECURITY CHECKS HERE
static surf *custromportraitload_surf;
custromportraitload_surf=NULL;
custromportraitload_surf=loadimage(t->d,SURF_SYSMEM16);
if (custromportraitload_surf){
HOST_portrait_data[HOST_portrait_next]=(unsigned short*)malloc(7168);
memcpy(HOST_portrait_data[HOST_portrait_next],custromportraitload_surf->o,7168);
HOST_portrait_loaded[HOST_portrait_next]=1;
tnpc3->port=HOST_portrait_next;
HOST_portrait_next++;
}
goto custromportraitload_found;
}//txtsame(t3,t4)
goto custromportraitload_loop;
}
}//playerlist[tpl]->GNPCflags[33]&1
custromportraitload_found:
custromportraitload_skip:
goto save_restored;
save_createcharacter: //new player
txtset(tnpc->name,tname);
tnpc->lev=1; tnpc->exp=370; //same as in original, incentive not to die!
tnpc->hp=30; tnpc->hp_max=30;
tnpc->s=0; tnpc->d=0; tnpc->i=0;
x=-1;
x++; if (t6->d[x]==0) {U6O_HONESTY} else {U6O_COMPASSION} //i3,d3
x++; if (t6->d[x]==0) {U6O_HONESTY} else {U6O_VALOR} //i3,s3
x++; if (t6->d[x]==0) {U6O_HONESTY} else {U6O_JUSTICE} //i3,X
x++; if (t6->d[x]==0) {U6O_HONESTY} else {U6O_SACRIFICE} //i3,X
x++; if (t6->d[x]==0) {U6O_HONESTY} else {U6O_HONOR} //i3,X
x++; if (t6->d[x]==0) {U6O_HONESTY} else {U6O_SPIRITUALITY} //i3,a1
x++; if (t6->d[x]==0) {U6O_HONESTY} else {U6O_HUMILITY} //i3,X
x++; if (t6->d[x]==0) {U6O_COMPASSION} else {U6O_VALOR} //d3,s3
x++; if (t6->d[x]==0) {U6O_COMPASSION} else {U6O_JUSTICE} //d3,X
x++; if (t6->d[x]==0) {U6O_COMPASSION} else {U6O_SACRIFICE} //d3,X
x++; if (t6->d[x]==0) {U6O_COMPASSION} else {U6O_HONOR} //d3,X
x++; if (t6->d[x]==0) {U6O_COMPASSION} else {U6O_SPIRITUALITY} //d3,a1
x++; if (t6->d[x]==0) {U6O_COMPASSION} else {U6O_HUMILITY} //d3,X
x++; if (t6->d[x]==0) {U6O_VALOR} else {U6O_JUSTICE} //s3,X
x++; if (t6->d[x]==0) {U6O_VALOR} else {U6O_SACRIFICE} //s3,X
x++; if (t6->d[x]==0) {U6O_VALOR} else {U6O_HONOR} //s3,X
x++; if (t6->d[x]==0) {U6O_VALOR} else {U6O_SPIRITUALITY} //s3,a1
x++; if (t6->d[x]==0) {U6O_VALOR} else {U6O_HUMILITY} //s3,X
x++; if (t6->d[x]==0) {U6O_JUSTICE} else {U6O_SACRIFICE} //i,d
x++; if (t6->d[x]==0) {U6O_JUSTICE} else {U6O_HONOR} //s,d
x++; if (t6->d[x]==0) {U6O_JUSTICE} else {U6O_SPIRITUALITY} //X,a1
x++; if (t6->d[x]==0) {U6O_JUSTICE} else {U6O_HUMILITY} //OK,X
x++; if (t6->d[x]==0) {U6O_SACRIFICE} else {U6O_HONOR} //s,i
x++; if (t6->d[x]==0) {U6O_SACRIFICE} else {U6O_SPIRITUALITY} //X,OK
x++; if (t6->d[x]==0) {U6O_SACRIFICE} else {U6O_HUMILITY} //a1,X
x++; if (t6->d[x]==0) {U6O_HONOR} else {U6O_SPIRITUALITY} //X,a1
x++; if (t6->d[x]==0) {U6O_HONOR} else {U6O_HUMILITY} //OK,X
x++; if (t6->d[x]==0) {U6O_SPIRITUALITY} else {U6O_HUMILITY} //a1,X
x=tnpc->s-8; if (x<1) x=1; tnpc->s=x;
x=tnpc->d-8; if (x<1) x=1; tnpc->d=x;
x=tnpc->i-8; if (x<1) x=1; tnpc->i=x;
tnpc->mp=tnpc->i*2; tnpc->mp_max=tnpc->i*2;
tnpc->wt=0; tnpc->wt_max=tnpc->s*4*100; tnpc->wt2=0; tnpc->wt2_max=tnpc->s*50;
//Debug new players get high stats, gold, exp, all spells,
if (U6O_DEBUG){
tnpc->lev=6;
tnpc->exp=410000;
tnpc->s=tnpc->s+3; tnpc->d=tnpc->d+3; tnpc->i=tnpc->i+18;
tnpc->wt=0; tnpc->wt_max=tnpc->s*4*100; tnpc->wt2=0; tnpc->wt2_max=tnpc->s*50;
//tnpc->mp_max=640; tnpc->mp=640;
tnpc->hp_max=180; tnpc->hp=180;
for (x=0;x<=9;x++){
x2=88; x3=0; x4=0;
if (x==8) {x2=57;}//spell
if (x<=7) {
x2=58;
for (x4=0;x4<=8;x4++){
x3=(x<<4)+x4;
myobj3=OBJnew(); myobj3->type=x2; myobj3->more2=x3; myobj3->info=0;//add item(s)
additem(tnpc,myobj3);
}
x3=(x<<4)+9;
x4=0;
}//spell
if (x2==88) x3=30000;//<-1000 gold
myobj3=OBJnew(); myobj3->type=x2; myobj3->more2=x3; myobj3->info=x4;//add item(s)
additem(tnpc,myobj3);
}//x
myobj3=OBJnew(); myobj3->type=65; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=66; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=67; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=68; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=69; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=70; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=71; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=72; myobj3->more2=1000; //<-reagents
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=87; myobj3->more2=0; myobj3->info=0;//add item: orb of the moons
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=242; myobj3->more2=0; myobj3->info=0;//rune of honesty
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=243; myobj3->more2=0; myobj3->info=0;//rune of compassion
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=244; myobj3->more2=0; myobj3->info=0;//rune of valor
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=81; myobj3->more2=0; myobj3->info=0;//storm cloack
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=258; myobj3->more2=0; myobj3->info=0;//invis ring
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=420; myobj3->more2=0; myobj3->info=0;//balloon
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=212; myobj3->more2=0; myobj3->info=0;//fan
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=50; myobj3->more2=15; //<-tcrossbow
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=23; myobj3->more2=255; //<-marmour
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=4; myobj3->more2=255; //<-spiked helm
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=35; myobj3->more2=255; //<-main gauche
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=35; myobj3->more2=255; //<-main gauche
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=13; myobj3->more2=255; //<-spiked shield
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=13; myobj3->more2=255; //<-spiked shield
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=24; myobj3->more2=255; //<-spiked collar
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=109; myobj3->more2=15; //<-rolling pin
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=109; myobj3->more2=15; //<-rolling pin
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=8; myobj3->more2=255; //<-magic helm
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=16; myobj3->more2=255; //<-magic shield
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=27; myobj3->more2=255; //<-leather boots
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=54; myobj3->more2=15; //<-magic bow
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=43; myobj3->more2=15; //<-sword
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=43; myobj3->more2=15; //<-sword
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=39; myobj3->more2=15; //<-mace
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=39; myobj3->more2=15; //<-mace
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=40; myobj3->more2=15; //<-morning star
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=40; myobj3->more2=15; //<-morning star
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=47; myobj3->more2=15; //<-halberd
additem(tnpc,myobj3);
}//U6O_DEBUG
//add items
myobj3=OBJnew(); myobj3->type=90; myobj3->more2=3; //<-torch
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=128; myobj3->more2=2; //<-bread
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=129; myobj3->more2=1; //<-meat
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=210; //<-ribs/big meat
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=74; myobj3->more2=0; //<-ankh
myobj3->info|=256; //quest item
additem(tnpc,myobj3);
myobj3=OBJnew(); myobj3->type=34; myobj3->more2=0; //<-club
additem(tnpc,myobj3);
if ((btime>=16)||(btime<=5)){ //only give players who enter at night
myobj3=OBJnew(); myobj3->type=90+1*1024; myobj3->more2=1; //<-torch in hand
tnpc->wep_left=myobj3;
}
static SYSTEMTIME systime;
GetLocalTime(&systime);
x3=(systime.wDay-1)+(systime.wMonth-1)*32+systime.wYear*(32*12);
playerlist[tpl]->GNPCflags[249]=x3; //249 YMD of character creation
txtset(t,"New_Player_Entered:"); txtadd(t,tnpc->name); LOGadd(t);
save_restored:
playerlist[tpl]->port=((npc*)playerlist[tpl]->party[0]->more)->port;
playerlist[tpl]->npcname=txtnew();
txtset(playerlist[tpl]->npcname,((npc*)playerlist[tpl]->party[0]->more)->name);
//if (tpl==0){
//if (U6O_DEBUG){
//tnpc->lev=8;
//tnpc->s=64; tnpc->d=64; tnpc->i=64;
//tnpc->mp_max=255; tnpc->mp=255;
//tnpc->hp_max=255; tnpc->hp=255;
//playerlist[tpl]->GNPCflags[6]=0;
//playerlist[tpl]->wizardeyetimeleft=0.0f;
//playerlist[tpl]->wizardeyex=0;
//playerlist[tpl]->wizardeyey=0;
//for (x=0;x<=2;x++){
//x2=88; x3=0; x4=0;
//if (x==0) {x2=58; x3=(6<<4)+9;}//spell
//if (x2==88) x3=20000;//<-1000 gold
//myobj3=OBJnew(); myobj3->type=x2; myobj3->more2=x3; myobj3->info=x4;//add item(s)
//additem(tnpc,myobj3);
//}//x
//}//U6O_DEBUG
//}//tpl==0
playerlist[tpl]->net=tnet;
playerlist[tpl]->id=U6ONEWID; U6ONEWID++;
playerlist[tpl]->GNPCflags[242]=socketclient_ip[tnet];//update IP
//log IP
txtset(t,"Player_IP:");
txtnumint(t2,playerlist[tpl]->GNPCflags[242]&255); txtadd(t,t2);
txtadd(t,".");
txtnumint(t2,(playerlist[tpl]->GNPCflags[242]>>8)&255); txtadd(t,t2);
txtadd(t,".");
txtnumint(t2,(playerlist[tpl]->GNPCflags[242]>>16)&255); txtadd(t,t2);
txtadd(t,".");
txtnumint(t2,(playerlist[tpl]->GNPCflags[242]>>24)&255); txtadd(t,t2);
LOGadd(t);
tnpc=(npc*)playerlist[tpl]->party[0]->more;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Entered Britannia: "); txtadd(t,tnpc->name);
for (x=0;x<=playerlist_last;x++){
if (playerlist[x]){
if (playerlist[x]->net!=INVALID_NET){
if (x!=tpl){
NET_send(NETplayer,playerlist[x]->net,t);
}}}}
inbritanniacheck(); txtset(t,"?"); t->d2[0]=8; txtadd(t,inbritannia); NET_send(NETplayer,playerlist[tpl]->net,t);
txtset(t3,motd);
txtset(t,"?"); t->d2[0]=2;
txtset(t2,"??"); t2->ds[0]=1; txtadd(t,t2);
t2->ds[0]=3; txtadd(t,t2);
t2->ds[0]=2047; txtadd(t,t2);
t2->ds[0]=1023; txtadd(t,t2);
t2->ds[0]=t3->l; txtadd(t,t2);
t2->ds[0]=0; txtadd(t,t2); //unused
t2->ds[0]=187; txtadd(t,t2); //more=port
txtset(t2,"????"); t2->df[0]=2; txtadd(t,t2); //wait
txtadd(t,t3);
NET_send(NETplayer,playerlist[tpl]->net,t);
txtset(t3,"??"); t3->d2[0]=14; t3->d2[1]=(windx+1)+(windy+1)*4; NET_send(NETplayer,playerlist[tpl]->net,t3);
//Compensation
//***KALDOSH BIT0 USED***
txtset(t,"Kaldosh"); if (txtsame(t,tnpc->name)){
if ((playerlist[tpl]->GNPCflags[246]&1)==0){ playerlist[tpl]->GNPCflags[246]|=1;
myobj3=OBJnew(); myobj3->type=87; myobj3->more2=0; myobj3->info=0;//add item: orb of the moons
additemroot(tnpc,myobj3);
}
}
if (tnamecolour){
playerlist[tpl]->GNPCflags[245]=tnamecolour;
}else{
if (playerlist[tpl]->GNPCflags[245]==0){
setnamecolour_getrandom:
x=rnd*256; x2=rnd*256; x3=rnd*256;
if ((x+x2+x3)<256) goto setnamecolour_getrandom;
playerlist[tpl]->GNPCflags[245]=x+(x2<<8)+(x3<<16);
}
}
//send namecolour to client
/*
txtsetchar(t,246);
txtaddchar(t,playerlist[tpl]->GNPCflags[245]&255);
txtaddchar(t,(playerlist[tpl]->GNPCflags[245]>>8)&255);
txtaddchar(t,(playerlist[tpl]->GNPCflags[245]>>16)&255);
NET_send(NETplayer,playerlist[tpl]->net,t);
*/
playerlist[tpl]->GNPCflags[36]=0;//cat abuse flag reset!
//auto-sysban
txtset(t2,tnpc->name); txtucase(t2);
tfh=open2("sysban.txt",OF_READWRITE|OF_SHARE_COMPAT);
if (tfh->h!=HFILE_ERROR){
sysban_nextplayer:
txtfilein(t,tfh); txtucase(t);
if (txtsame(t,t2)){
txtsetchar(t3,247); txtaddchar(t3,1); NET_send(NETplayer,playerlist[tpl]->net,t3);//SYSBAN ON
}
if (t->l) goto sysban_nextplayer;
close(tfh);
}
for (x=0;x<=7;x++){
if (playerlist[tpl]->party[x]){
if (playerlist[tpl]->GNPCflags[230+x]){
myobj2=playerlist[tpl]->party[x]; tnpc2=(npc*)myobj2->more;
//move them to death spot
OBJmove_allow=TRUE;
OBJmove2(myobj2,playerlist[tpl]->GNPCflags[230+x]&65535,playerlist[tpl]->GNPCflags[230+x]>>16);
OBJmove_allow=FALSE;
playerlist[tpl]->GNPCflags[230+x]=0;
//now kill them using a callback!
//the callback will do all the hard work for me
tplayer=playerlist[tpl];
myobj2=tplayer->party[x];
tnpc=(npc*)myobj2->more;
login_dead_callback=1; goto login_dead;
login_dead2: login_dead_callback=0;
}
}
}
//tplayer->GNPCflags[230+resu_partymember[i3]]=resu_x[i3]+(resu_y[i3]<<16);
goto doneclmess;
foundclient:
playerlist[tpl]->idle_connect=0;
if (t->d2[0]==251) goto doneclmess;
if (playerlist[tpl]->playinstrument){ //stop playing instrument?
x2=0;
x=t->d2[0];
if (x==5) x2=1;
if (x==6) x2=1;
if (x==7) x2=1;
if (x==12) x2=1;
if (x==13) x2=1;
if (x==15) x2=1;
if (x==16) x2=1;
if (x==17) x2=1;
if (x==19) x2=1;
if (x==20) x2=1;
if (x==21) x2=1;
if (x2){
playerlist[tpl]->playinstrument--;
if (playerlist[tpl]->playinstrument==0){
txtset(t2,"?"); t2->d2[0]=29; NET_send(NETplayer,playerlist[tpl]->net,t2);
}//==0
}//x2
}//playinstrument
//cancel wizardeye
if (playerlist[tpl]->wizardeyetimeleft){
x2=0; x=t->d2[0];
if (x==6) x2=1;
if (x==7) x2=1;
if (x==12) x2=1;
if (x==13) x2=1;
if (x==15) x2=1;
if (x==16) x2=1;
if (x==17) x2=1;
if (x==19) x2=1;
if (x==20) x2=1;
if (x==21) x2=1;
if (x2){
txtset(t2,"??"); t2->d2[0]=36; t2->d2[1]=0; NET_send(NETplayer,playerlist[tpl]->net,t2);
playerlist[tpl]->wizardeyetimeleft=0.0f;
}
}
//process client message
//???? if (NETplayer==tnet) CLIENTplayer=playerlist[tpl]; //CLIENTplayer<-tpl switch to player tpl
if (t->d2[0]==244){//send leaving britannia message
if (playerlist[tpl]->party[0]){
myobj=playerlist[tpl]->party[0]; tnpc=(npc*)myobj->more;
//1. send status message to ALL PLAYERS
txtsetchar(t2,8);
txtadd(t2,"Leaving Britannia: ");
txtadd(t2,tnpc->name);
for (z=0;z<=playerlist_last;z++){ if (z!=tpl){ if (playerlist[z]){ if (playerlist[z]->net){
NET_send(NETplayer,playerlist[z]->net,t2);
}}}}
//2. send a local text sfx message
//Virtue @is @leaving @Britannia (the red text is specifically to stop people pretending to leave)
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=3;
sf[i3].x=myobj->x; sf[i3].y=myobj->y-2;
sf[i3].wait=2;
sf[i3].more=tnpc->port;
static txt* inouttxt;
inouttxt=txtnew();
txtset(inouttxt,"");
txtset(t2,tnpc->name); txtadd(t2," is leaving Britannia.");
txtaddcolouredname(inouttxt,t2,playerlist[tpl]);
sf[i3].p=inouttxt;
}//party[0]
goto doneclmess;
}
if (t->d2[0]==248){//respawn
playerlist[tpl]->respawn=255;
if (t->l==2) playerlist[tpl]->respawn=t->d2[1];
goto doneclmess;
}
if (t->d2[0]==5){
playerlist[tpl]->idle=0;
txtright(t,t->l-1);
if (playerlist[tpl]->readmessage==FALSE){
memcpy(&playerlist[tpl]->mf,t->d,(DWORD)&playerlist[tpl]->mobj-(DWORD)&playerlist[tpl]->mf);
playerlist[tpl]->readmessage=TRUE;
} //not second general input message
else{ //second input message (interpret carefully)
//update arrow keys
x=t->d2[7]+(t->d2[8]<<8)+(t->d2[9]<<16)+(t->d2[10]<<24);
if (playerlist[tpl]->key&KEYup) playerlist[tpl]->key-=KEYup;
playerlist[tpl]->key+=(x&KEYup);
if (playerlist[tpl]->key&KEYdown) playerlist[tpl]->key-=KEYdown;
playerlist[tpl]->key+=(x&KEYdown);
if (playerlist[tpl]->key&KEYleft) playerlist[tpl]->key-=KEYleft;
playerlist[tpl]->key+=(x&KEYleft);
if (playerlist[tpl]->key&KEYright) playerlist[tpl]->key-=KEYright;
playerlist[tpl]->key+=(x&KEYright);
playerlist[tpl]->key|=(x&KEYup2);
playerlist[tpl]->key|=(x&KEYdown2);
playerlist[tpl]->key|=(x&KEYleft2);
playerlist[tpl]->key|=(x&KEYright2);
} //second general input message
//cancel wizardeye
if (playerlist[tpl]->key&(KEYmbclick+KEYbreakcombat+KEYquan+KEYf1)){
if (playerlist[tpl]->wizardeyetimeleft){
if (playerlist[tpl]->key&KEYmbclick) playerlist[tpl]->key-=KEYmbclick;
txtset(t2,"??"); t2->d2[0]=36; t2->d2[1]=0; NET_send(NETplayer,playerlist[tpl]->net,t2);
playerlist[tpl]->wizardeyetimeleft=0.0f;
}
}
goto doneclmess;
} //5
if (t->d2[0]==37){
if (t->l<=3072){//IMPORTANT: ANY VOICE DATA ABOVE 3K IS IGNORED
if (playerlist[tpl]->GNPCflags[33]&4){
txtsetchar(t,250); txtaddchar(t,10); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}
if (myobj=getprimarypartymemberobj(playerlist[tpl])){
tnpc=(npc*)myobj->more;
txtsetchar(t2,38);
txtaddshort(t2,tnpc->port);
txtset(t4,tnpc->name); txtadd(t4,":");
txtset(t3,""); txtaddcolouredname(t3,t4,playerlist[tpl]);
txtaddchar(t2,t3->l); txtadd(t2,t3);
txtaddshort(t2,playerlist[tpl]->x); txtaddshort(t2,playerlist[tpl]->y);
txtset(t3,t2);//t3=info but no voice data
txtright(t,t->l-1);
txtadd(t2,t);//add compressed voice data
x2=playerlist[tpl]->x; y2=playerlist[tpl]->y;
for (z=0;z<=playerlist_last;z++){ if (z!=tpl){ if (playerlist[z]){ if (playerlist[z]->net){
//x3=playerlist[z]->x-15; y3=playerlist[z]->y-11;
//if (x3<0) x3=0; if (y3<0) y3=0; if (x3>2016) x3=2016; if (y3>1000) y3=1000;
getscreenoffset(playerlist[z]->x,playerlist[z]->y,&x3,&y3);
if ((x2>=x3)&&(x2<(x3+32))){ if ((y2>=y3)&&(y2<(y3+24))){
if (playerlist[z]->mixer_volume){
NET_send(NETplayer,playerlist[z]->net,t2);
}else{
NET_send(NETplayer,playerlist[z]->net,t3);
}
}}
}}}}//x2 loop & checks
}//myobj
}//data size limit
goto doneclmess;
}//37
if (t->d2[0]==39){//update player->miver_volume on host
playerlist[tpl]->mixer_volume=t->d2[1];
goto doneclmess;
}//39
if (t->d2[0]==40){//get volume levels of other players in area
txtset(t,"?");
txtset(t2,"????");
txtset(t3,"?");
t->d2[0]=41;
//(x2,y2)=top-left corner of requesting player's screen
//x2=playerlist[tpl]->x-15; y2=playerlist[tpl]->y-11; if (x2<0) x2=0; if (y2<0) y2=0; if (x2>2016) x2=2016; if (y2>1000) y2=1000;
getscreenoffset(playerlist[tpl]->x,playerlist[tpl]->y,&x2,&y2);
for (z=0;z<=playerlist_last;z++){ if (z!=tpl){ if (playerlist[z]){ if (playerlist[z]->net){
x3=playerlist[z]->x; y3=playerlist[z]->y;
if ((x3>=x2)&&(x3<(x2+32))){ if ((y3>=y2)&&(y3<(y2+24))){
if (myobj=playerlist[z]->party[0]){
txtaddlong(t,playerlist[z]->id);
txtaddchar(t,playerlist[z]->mixer_volume);
}else{
//send volume at last known position
txtaddlong(t,0xFFFFFFFF);//ID not being sent, use static position
txtaddshort(t,x3); txtaddshort(t,y3);
txtaddchar(t,playerlist[z]->mixer_volume);
}
}}
}}}}//z loop & checks
if (t->l>1){
NET_send(NETplayer,playerlist[tpl]->net,t);
}
if (playerlist[tpl]->GNPCflags[33]&4) goto doneclmess;//don't update "speaking..." if banned
playerlist[tpl]->speaking=3.0f;
goto doneclmess;
}//40
if (t->d2[0]==42){//request portrait data
////goto doneclmess;
txtright(t,t->l-1);
x2=t->ds[0];
if (HOST_portrait_loaded[x2]){
txtsetchar(t,43); txtaddshort(t,x2);
/*
LOSS-LESS COMPRESS PORTRAIT DATA
loop:
2bits (V0-V3)
V0 repeat last known (last known starts off as black)
{
5bits 1-32 repeats
loop
}
V1 can't be created
{
5:5:5bits fixed colour
loop
}
V2 accend
{
3bits blue
3bits green
3bits red
loop
}
V3 decend
{
3bits blue
3bits green
3bits red
loop
}
*/
static unsigned long bitsi;
bitsi=0;
static unsigned short *sp;
txtNEWLEN(t2,-16384);
static long r,g,b,r2,g2,b2,r3,g3,b3,repeat;
sp=HOST_portrait_data[x2];
b=0; g=0; r=0;
repeat=0;
for (x3=0;x3<=3583;x3++){
b2=sp[x3]&31; g2=(sp[x3]>>6)&31; r2=(sp[x3]>>11)&31;
if ((b==b2)&&(g==g2)&&(r==r2)&&(repeat<32)){
repeat++; goto llc_pixeldone;
}
if (repeat){
BITSadd(t2,&bitsi,0,2); BITSadd(t2,&bitsi,repeat-1,5);
repeat=0;
}
b3=b2; if (b3<b) b3+=32;
g3=g2; if (g3<g) g3+=32;
r3=r2; if (r3<r) r3+=32;
if (((b3-b)<=7)&&((g3-g)<=7)&&((r3-r)<=7)){//compression possible
if (((b3-b)>=0)&&((g3-g)>=0)&&((r3-r)>=0)){//compression possible
//if ((b2>=b)&&(g2>=g)&&(r2>=r)){//ascending
//if (((b2-b)<=7)&&((g2-g)<=7)&&((r2-r)<=7)){//compression possible
BITSadd(t2,&bitsi,2,2);
BITSadd(t2,&bitsi,b3-b,3);
BITSadd(t2,&bitsi,g3-g,3);
BITSadd(t2,&bitsi,r3-r,3);
goto llc_pixeldone;
}
}
b3=b2; if (b3>b) b3-=32;
g3=g2; if (g3>g) g3-=32;
r3=r2; if (r3>r) r3-=32;
if (((b3-b)>=-7)&&((g3-g)>=-7)&&((r3-r)>=-7)){//compression possible
if (((b3-b)<=0)&&((g3-g)<=0)&&((r3-r)<=0)){//compression possible
//if ((b2<=b)&&(g2<=g)&&(r2<=r)){//decending
//if (((b-b2)<=7)&&((g-g2)<=7)&&((r-r2)<=7)){//compression possible
BITSadd(t2,&bitsi,3,2);
BITSadd(t2,&bitsi,b-b3,3);
BITSadd(t2,&bitsi,g-g3,3);
BITSadd(t2,&bitsi,r-r3,3);
goto llc_pixeldone;
}
}
BITSadd(t2,&bitsi,1,2);//no optomization was possible :(
BITSadd(t2,&bitsi,b2,5);
BITSadd(t2,&bitsi,g2,5);
BITSadd(t2,&bitsi,r2,5);
llc_pixeldone:
b=b2; g=g2; r=r2;
}//x3
if (repeat){
BITSadd(t2,&bitsi,0,2); BITSadd(t2,&bitsi,repeat-1,5);
}
t2->l=bitsi>>3; if (bitsi&7) t2->l++; t2->d2[t2->l]=0;
//exit(t2->l);
//4776
//BITSadd(t,&bitsi,z,8);//scene update
/*
3959 Kaldosh
4447 Mose
4714 Virtue
1 if on the last known colour value (default is black) should be repeated
if(on){
loop
}
1 if on the following colour can't be "created"
if (on){
5:5:5 fixed colour
loop
}
1 if on acending else decending
static unsigned short *sp;
txtNEWLEN(t2,-7168);
//memcpy(t2->d,HOST_portrait_data[x2],7168);
//6233
//11 11 11
/*
bit 0: rle compression (yes/no)
bit 1: increase brightness (yes/no)
bits [2-3]: blue
bits [4-5]: green
bits [6-7]: red
0 rle compression
1 increase brightness
2 decrease brightness
3 ?
bit 0
bit 1
(if sensitive compression means increase brightness)
bit 2-3 red (0-3)
bit 2-3 green (0-3)
bit 2-3 blue (0-3)
next 6 bits
sp=HOST_portrait_data[x2];
y2=-1;
y4=0;
x5=0;
for (x3=0;x3<=3584;x3++){
y3=sp[x3]; if (y3&32) y3-=32;
if ((y3!=y2)||(y4==128)||(x3==3584)){
if (y2!=-1){
if (y4){
//repeats
t2->d2[x5]=(y2&255)+32; x5++;
t2->d2[x5]=(y2>>8)&255; x5++;
t2->d2[x5]=y4-1; x5++;
}else{//y4
//no repeats
t2->d2[x5]=y2&255; x5++;
t2->d2[x5]=(y2>>8)&255; x5++;
}//y4
}//y2!=-1
y2=y3;
y4=0;
}else{
y4++;
}
}//x3
t2->d2[x5]=0;
t2->l=x5;
//rescan using sensitive compression avoiding rle content
static long r,g,b,r2,g2,b2;
txtNEWLEN(t3,-7168);
y2=-1;//last known colour value
x5=0;
for (x3=0;x3<t2->l;x3++){
y3=t2->d2[x3];
if (y3&32){//rle content
y2=-1; //(y3-32)+(t2->d2[x3+1]<<8);//last known color value
t3->d2[x5]=y3; x5++; x3++;
t3->d2[x5]=t2->d2[x3]; x5++; x3++;
t3->d2[x5]=t2->d2[x3]; x5++;
goto skiprlecontent;
}
if (y2!=-1){
//is y3 close to y2
b=y2&31; g=(y2>>6)&31; r=(y2>>11)&31;
b2=y3&31; g2=(y3>>6)&31; r2=(y3>>11)&31;
y4=0;
if ((b2>=b)&&(g2>=g)&&(r2>=r)) y4=1;
if ((b2<=b)&&(g2<=g)&&(r2<=r)) y4=-1;
if (y4==1){
if (((b2-b)<=3)&&((g2-g)<=3)&&((r-r2)<=3)){
MessageBox(NULL,"saved another assending byte","Ultima 6 Online",MB_OK);
}
}
if (y4==-1){
if (((b-b2)<=3)&&((g-g2)<=3)&&((r-r2)<=3)){
MessageBox(NULL,"saved another decending byte","Ultima 6 Online",MB_OK);
}
}
//add as is
t3->d2[x5]=y3; x5++; x3++;
t3->d2[x5]=t2->d2[x3]; x5++;
}else{
//add as is
t3->d2[x5]=y3; x5++; x3++;
t3->d2[x5]=t2->d2[x3]; x5++;
}
y2=y3;//last known colour value
skiprlecontent:;
}//x3
t3->d2[x5]=0;
t3->l=x5;
exit (t2->l);
*/
txtadd(t,t2);
NET_send(NETplayer,playerlist[tpl]->net,t);
}//HOST_portrait_loaded[x2]
goto doneclmess;
}//42
if (t->d2[0]==45){
if (myobj=playerlist[tpl]->party[t->d2[1]]){
tnpc=(npc*)myobj->more;
x2=t->ds[1]-120; y2=t->ds[2]-120;
if ((x2>=0)&&(y2>=0)){
x2/=32;
y2/=32;
x2=y2*4+x2;
x2+=tnpc->baseitem_offset;
if (myobj=(object*)tnpc->baseitem->more){
setnot4sale:
if (myobj){
if (x2){
x2--;
myobj=(object*)myobj->next;
goto setnot4sale;
}
if ((obji[sprlnk[myobj->type&1023]].flags&(1+2+4+8+16+32+64))==0){
txtsetchar(t2,8); txtaddchar(t2,255); txtadd(t2,"Only wieldable items may be marked as not for sale."); NET_send(NETplayer,playerlist[tpl]->net,t2);
goto doneclmess;
}
if (myobj->info&256){
txtsetchar(t2,8); txtaddchar(t2,255); txtadd(t2,"Quest items cannot be marked as not for sale."); NET_send(NETplayer,playerlist[tpl]->net,t2);
goto doneclmess;
}
if (obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].flags&4096){
txtsetchar(t2,8); txtaddchar(t2,255); txtadd(t2,"That cannot be marked as not for sale."); NET_send(NETplayer,playerlist[tpl]->net,t2);
goto doneclmess;
}
if (obji[sprlnk[myobj->type&1023]].flags&1024){ //container
txtsetchar(t2,8); txtaddchar(t2,255); txtadd(t2,"That cannot be marked as not for sale."); NET_send(NETplayer,playerlist[tpl]->net,t2);
goto doneclmess;
}
if (myobj->type==16){//magic shield
txtsetchar(t2,8); txtaddchar(t2,255); txtadd(t2,"That cannot be marked as not for sale."); NET_send(NETplayer,playerlist[tpl]->net,t2);
goto doneclmess;
}
myobj->info^=32768;
tnpc->upflags|=32;
}//myobj
}//myobj of baseitem->more
}//x2,y2
goto doneclmess;
}
}//45
/*
if ((CLIENTplayer->key&KEYmbclick)&&(userkey==5)){
userkey=0; CLIENTplayer->key-=KEYmbclick;
//send message to host
if (CLIENTplayer->mf<=7){
txtsetchar(t2,45); txtaddchar(t2,CLIENTplayer->mf);
txtaddshort(t2,CLIENTplayer->mx); txtaddshort(t2,CLIENTplayer->my);
NET_send(NETplayer,NULL,t2);
}//CLIENTplayer->mf<=7
}//not4sale
*/
if ((t->d2[0]==6)||(t->d2[0]==12)){
playerlist[tpl]->typing=0;
playerlist[tpl]->idle=0;
x5=0; if (t->d2[0]==12){
x5=1; //global message
if (playerlist[tpl]->globalmessage_wait!=0){
txtset(t,"?"); t->d2[0]=8; txtaddchar(t,255); txtadd(t,"Wait 10 seconds between sending global messages!");
NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}
playerlist[tpl]->globalmessage_wait=11-1;
}
txtright(t,t->l-1);
if (t->d2[0]==47){//"/"
//PRIVILEGES: change
/*
PRIVILEGES: notes
40-47 16x2-bit privilege settings representing privilege level from 0-3
PRIVILEGE LEVEL 1 You can use the power on others eg. /BAN John
You can revoke this LEVEL 1 PRIVILEGE from others eg. /UNGRANT BAN John (with the same privilege level or less)
PRIVILEGE LEVEL 2 You can use the power on others eg. /BAN John
You can give another the ability to use that power eg. /GRANT BAN John
You can revoke this LEVEL 2 PRIVILEGE from others eg. /UNGRANT2 BAN John (with the same privilege level or less)
PRIVILEGE LEVEL 3 You can use the power on others eg. /BAN John
You can give another the ability to use that power eg. /GRANT BAN John
You can give another the ability to give that power to others eg. /GRANT2 BAN John
You can give another the ability to "give another the ability to give that power to others" eg. /GRANT3 BAN John
You can revoke this LEVEL 3 PRIVILEGE from others eg. /UNGRANT3 BAN John (with the same privilege level or less)
*/
static unsigned char privileges_index;
txtset(t2,t);
txtright(t2,t2->l-1);
static unsigned char privileges_levelrequiredtochange;
static unsigned char privileges_set;
static unsigned char privileges_leveltochange;
txtset(t3,"GRANT "); if (txtsearch(t2,t3)==1) {privileges_leveltochange=1; privileges_set=TRUE; privileges_levelrequiredtochange=2; goto privelegechange_requested;}
txtset(t3,"UNGRANT "); if (txtsearch(t2,t3)==1) {privileges_leveltochange=1; privileges_set=FALSE; privileges_levelrequiredtochange=1; goto privelegechange_requested;}
txtset(t3,"GRANT2 "); if (txtsearch(t2,t3)==1) {privileges_leveltochange=2; privileges_set=TRUE; privileges_levelrequiredtochange=3; goto privelegechange_requested;}
txtset(t3,"UNGRANT2 "); if (txtsearch(t2,t3)==1) {privileges_leveltochange=2; privileges_set=FALSE; privileges_levelrequiredtochange=2; goto privelegechange_requested;}
txtset(t3,"GRANT3 "); if (txtsearch(t2,t3)==1) {privileges_leveltochange=3; privileges_set=TRUE; privileges_levelrequiredtochange=3; goto privelegechange_requested;}
txtset(t3,"UNGRANT3 "); if (txtsearch(t2,t3)==1) {privileges_leveltochange=3; privileges_set=FALSE; privileges_levelrequiredtochange=3; goto privelegechange_requested;}
goto privelegechange_skip;
privelegechange_requested:
txtright(t2,t2->l-t3->l);
txtset(t3,"BAN "); if (txtsearch(t2,t3)==1) {privileges_index=0; goto privelegechange_gotcommand;}
txtset(t3,"UNBAN "); if (txtsearch(t2,t3)==1) {privileges_index=1; goto privelegechange_gotcommand;}
txtset(t3,"KICK "); if (txtsearch(t2,t3)==1) {privileges_index=2; goto privelegechange_gotcommand;}
txtset(t3,"DELETEPORTRAIT "); if (txtsearch(t2,t3)==1) {privileges_index=3; goto privelegechange_gotcommand;}
txtset(t3,"BLOCKPORTRAITUPLOAD "); if (txtsearch(t2,t3)==1) {privileges_index=4; goto privelegechange_gotcommand;}
txtset(t3,"UNBLOCKPORTRAITUPLOAD "); if (txtsearch(t2,t3)==1) {privileges_index=5; goto privelegechange_gotcommand;}
txtset(t3,"BANVOICECHAT "); if (txtsearch(t2,t3)==1) {privileges_index=6; goto privelegechange_gotcommand;}
txtset(t3,"UNBANVOICECHAT "); if (txtsearch(t2,t3)==1) {privileges_index=7; goto privelegechange_gotcommand;}
txtset(t3,"SETMOTD "); if (txtsearch(t2,t3)==1) {privileges_index=8; goto privelegechange_gotcommand;}
txtset(t3,"SYSBAN "); if (txtsearch(t2,t3)==1) {privileges_index=9; goto privelegechange_gotcommand;}
txtset(t3,"UNSYSBAN "); if (txtsearch(t2,t3)==1) {privileges_index=9; goto privelegechange_gotcommand;}
txtset(t3,"BANIP "); if (txtsearch(t2,t3)==1) {privileges_index=10; goto privelegechange_gotcommand;}
txtset(t3,"UNBANIP "); if (txtsearch(t2,t3)==1) {privileges_index=11; goto privelegechange_gotcommand;}
txtset(t3,"GETIP "); if (txtsearch(t2,t3)==1) {privileges_index=12; goto privelegechange_gotcommand;}
//...
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Privileges change failed! (name of privilege to change is invalid)"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
privelegechange_gotcommand:
//PRIVILEGES: check requesting player has sufficient privileges
static unsigned char privileges_requestingplayerlevel;
x3=privileges_index/16;//globalflags[x3]
x4=privileges_index-x3*16;//sub-index
x4*=2;//multiply sub-index to get shifting factor
privileges_requestingplayerlevel=(playerlist[tpl]->GNPCflags[x3+40]>>x4)&3; if (privileges_requestingplayerlevel<privileges_levelrequiredtochange) goto privilege_denied;
/*
//set x6 to (0-2)privilege level required
if (x2&1){
x6=x2/2;
}else{
if (x2<=1) x6=1; else x6=2;
}
x4=x3/32;//DWORD privilege is stored at (0-3)
x5=x3&31;//bit privilege is stored at
x6=x4+x6*4+40;
if ((playerlist[tpl]->GNPCflags[x6]&(1<<x5))==0) goto privilege_denied;
x6=x4+(x2/2)*4+40;
*/
txtright(t2,t2->l-t3->l);
//check name against characters currently in britannia
for (y2=0;y2<=playerlist_last;y2++){ if (playerlist[y2]){
if (myobj2=getprimarypartymemberobj(playerlist[y2])){ tnpc2=(npc*)myobj2->more;
if (txtsamewithoutcase(tnpc2->name,t2)){
//PRIVILEGES: check requesting player's privilege level is equal or higher than target player's privilege level
static unsigned char privileges_targetplayerlevel;
privileges_targetplayerlevel=(playerlist[y2]->GNPCflags[x3+40]>>x4)&3; if (privileges_requestingplayerlevel<privileges_targetplayerlevel) goto privilege_denied;
x5=privileges_targetplayerlevel;
//PRIVILEGES: edit privileges
if (privileges_set){
if (privileges_targetplayerlevel<privileges_leveltochange){
privileges_targetplayerlevel=privileges_leveltochange;
}else{
txtsetchar(t2,8); txtadd(t2,"Privileges change failed! (player already has these privileges)"); NET_send(NETplayer,playerlist[tpl]->net,t2); goto doneclmess;
}
}else{//privileges_set: remove privilege
if (privileges_targetplayerlevel>(privileges_leveltochange-1)){
privileges_targetplayerlevel=privileges_leveltochange-1;
}else{
txtsetchar(t2,8); txtadd(t2,"Privileges change failed! (player does not currently have this privilege so privileges have not been changed)"); NET_send(NETplayer,playerlist[tpl]->net,t2); goto doneclmess;
}
}//privileges_set
playerlist[y2]->GNPCflags[x3+40]-=(x5<<x4);//remove old privileges
playerlist[y2]->GNPCflags[x3+40]+=(privileges_targetplayerlevel<<x4);//add new privileges
txtset(t2,"?"); t2->d2[0]=8; txtadd(t2,"Privileges changed successfully! ("); txtadd(t2,t); txtadd(t2,")"); NET_send(NETplayer,playerlist[tpl]->net,t2);
//record change on file record in save folder
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
goto doneclmess;
}//name==t2
}//party[0]
}}//y2 loop
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Privileges change failed! (no player named "); txtadd(t,t2); txtadd(t," is currently online, check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
privelegechange_skip:
//slash commands
txtset(t3,"KICK "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=2; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=FIRST_CLIENT;x4<=playerlist_last;x4++){
if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (((playerlist[x4]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)>((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)) goto privilege_denied2;
playerlist[x4]->GNPCflags[253]|=1;
txtset(t,"??"); t->d2[0]=250; t->d2[1]=7; NET_send(NETplayer,playerlist[x4]->net,t);
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}
txtset(t3,"BAN "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=0; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
txtset(t9,"Kalour"); if (txtsamewithoutcase(t9,t2)) goto privilege_denied2;
x5=0;
for (x4=0;x4<=playerlist_last;x4++){ if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (x4==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}
x5=1;
}}}}
tfh=open2("ban.txt",OF_READWRITE|OF_SHARE_COMPAT); seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
if (x5){
txtset(t3,"?"); t3->d2[0]=8; txtadd(t3,t2); txtadd(t3," has been banned!"); NET_send(NETplayer,playerlist[tpl]->net,t3);
}else{
txtset(t3,"?"); t3->d2[0]=8; txtadd(t3,t2); txtadd(t3," is not currently in Britannia but has been banned!"); NET_send(NETplayer,playerlist[tpl]->net,t3);
}
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
goto doneclmess;
}
txtset(t3,"UNBAN "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=1; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
txtucase(t2);
tfh=open2("ban.txt",OF_READWRITE|OF_SHARE_COMPAT);
y=0;
unban_loop:
x4=seek(tfh); txtfilein(t3,tfh);
if (t3->l){
txtucase(t3);
if (txtsame(t2,t3)){
y=1;
seek(tfh,x4);
for (y2=0;y2<t3->l;y2++) t3->d2[y2]=42;
txtfileout(t3,tfh);
}//txtsame(t2,t3)
}//t3->l
if (x4<lof(tfh)) goto unban_loop;
close(tfh);
if (y){
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," was unbanned successfully!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}else{
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,"No player named "); txtadd(t4,t2); txtadd(t4," is currently banned!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
goto doneclmess;
}
txtset(t3,"DELETEPORTRAIT "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=3; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=0;x4<=playerlist_last;x4++){ if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (((playerlist[x4]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)>((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)) goto privilege_denied2;
if (playerlist[x4]->GNPCflags[33]&1){
playerlist[x4]->GNPCflags[33]--;
playerlist[x4]->GNPCflags[253]|=1;//kick to stop player using existing portrait
tnpc2->exp+=1000;
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4,"'s custom portrait deleted! (1000xp returned)"); NET_send(NETplayer,playerlist[tpl]->net,t4);
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
txtset(t,"??"); t->d2[0]=250; t->d2[1]=7; NET_send(NETplayer,playerlist[x4]->net,t);
}else{
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," is not using a custom portrait!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}
txtset(t3,"BLOCKPORTRAITUPLOAD "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=4; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=FIRST_CLIENT;x4<=playerlist_last;x4++){
if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (((playerlist[x4]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)>((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)) goto privilege_denied2;
if ((playerlist[x4]->GNPCflags[33]&2)==0){
playerlist[x4]->GNPCflags[33]|=2;
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," can no longer upload custom portraits!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
}else{
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," already cannot upload custom portraits!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}
txtset(t3,"UNBLOCKPORTRAITUPLOAD "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=5; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=0;x4<=playerlist_last;x4++){ if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (playerlist[x4]->GNPCflags[33]&2){
playerlist[x4]->GNPCflags[33]-=2;
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," can now upload custom portraits again!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
}else{
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," can already upload custom portraits!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}
txtset(t3,"BANVOICECHAT "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=6; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=FIRST_CLIENT;x4<=playerlist_last;x4++){
if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (((playerlist[x4]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)>((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)) goto privilege_denied2;
if ((playerlist[x4]->GNPCflags[33]&4)==0){
playerlist[x4]->GNPCflags[33]|=4;
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," is now banned from using voice chat!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
}else{
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," is already banned from using voice chat!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}
txtset(t3,"UNBANVOICECHAT "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=7; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=0;x4<=playerlist_last;x4++){ if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (playerlist[x4]->GNPCflags[33]&4){
playerlist[x4]->GNPCflags[33]-=4;
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," can now use voice chat again!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
}else{
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," can already use voice chat!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}
txtset(t3,"SETMOTD "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=8; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
txtset(motd,t2);
tfh=open2("motd.txt",OF_READWRITE|OF_SHARE_COMPAT|OF_CREATE);
txtfileout(motd,tfh);
close(tfh);
txtset(t,"?"); t->d2[0]=8; txtadd(t,"MOTD set to \""); txtadd(t,t2); txtadd(t,"\""); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}//SETMOTD
txtset(t3,"SYSBAN "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=9; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=FIRST_CLIENT;x4<=playerlist_last;x4++){
if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (((playerlist[x4]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)>((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)) goto privilege_denied2;
txtsetchar(t,247); txtaddchar(t,1); NET_send(NETplayer,playerlist[x4]->net,t);//SYSBAN ON
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," is now system banned! (In Britannia time limited to 8 seconds)"); NET_send(NETplayer,playerlist[tpl]->net,t4);
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}//SYSBAN
txtset(t3,"UNSYSBAN "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=9; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=0;x4<=playerlist_last;x4++){ if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
if (((playerlist[x4]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)>((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)) goto privilege_denied2;
txtsetchar(t,247); txtaddchar(t,0); NET_send(NETplayer,playerlist[x4]->net,t);//SYSBAN OFF
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,t2); txtadd(t4," has been sent a release system ban message! (If the client has already quit this message may not have been received)"); NET_send(NETplayer,playerlist[tpl]->net,t4);
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}//UNSYSBAN
txtset(t3,"BANIP "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=10; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
txtset(t9,"Kalour"); if (txtsamewithoutcase(t9,t2)) goto privilege_denied2;
for (x4=FIRST_CLIENT;x4<=playerlist_last;x4++){
if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
tfh=open2("banip.txt",OF_READWRITE|OF_SHARE_COMPAT);
if (tfh->h==HFILE_ERROR) tfh=open2("banip.txt",OF_READWRITE|OF_SHARE_COMPAT|OF_CREATE);
seek(tfh,lof(tfh));
txtset(t4,"");
txtnumint(t3,playerlist[x4]->GNPCflags[242]&255); txtadd(t4,t3); txtadd(t4,".");
txtnumint(t3,(playerlist[x4]->GNPCflags[242]>>8)&255); txtadd(t4,t3); txtadd(t4,".");
txtnumint(t3,(playerlist[x4]->GNPCflags[242]>>16)&255); txtadd(t4,t3); txtadd(t4,".");
txtnumint(t3,(playerlist[x4]->GNPCflags[242]>>24)&255); txtadd(t4,t3);
txtfileout(t4,tfh);
close(tfh);
txtset(t3,"?"); t3->d2[0]=8; txtadd(t3,t2); txtadd(t3,"'s IP has been banned!"); NET_send(NETplayer,playerlist[tpl]->net,t3);
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}//BANIP
txtset(t3,"UNBANIP "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=11; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
txtucase(t2);
tfh=open2("banip.txt",OF_READWRITE|OF_SHARE_COMPAT);
if (tfh->h==HFILE_ERROR){
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,"The IP "); txtadd(t4,t2); txtadd(t4," is not currently banned!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
goto doneclmess;
}
y=0;
unbanip_loop:
x4=seek(tfh); txtfilein(t3,tfh);
if (t3->l){
txtucase(t3);
if (txtsame(t2,t3)){
y=1;
seek(tfh,x4);
for (y2=0;y2<t3->l;y2++) t3->d2[y2]=46;//"."
txtfileout(t3,tfh);
}//txtsame(t2,t3)
}//t3->l
if (x4<lof(tfh)) goto unbanip_loop;
close(tfh);
if (y){
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,"The IP "); txtadd(t4,t2); txtadd(t4," was unbanned successfully!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
txtset(t2,"UNKNOWN"); if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more; txtset(t2,tnpc2->name);}
txtadd(t2,": "); txtadd(t2,t);
tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_SHARE_COMPAT); if (tfh->h==HFILE_ERROR) tfh=open2(".\\save\\adminlog.txt",OF_READWRITE|OF_CREATE);
seek(tfh,lof(tfh)); txtfileout(t2,tfh); close(tfh);
}else{
txtset(t4,"?"); t4->d2[0]=8; txtadd(t4,"The IP "); txtadd(t4,t2); txtadd(t4," is not currently banned!"); NET_send(NETplayer,playerlist[tpl]->net,t4);
}
goto doneclmess;
}//UNBANIP
txtset(t3,"GETIP "); if (txtsearch(t2,t3)==1){ txtright(t2,t2->l-t3->l);
privileges_index=12; if (((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)==0) goto privilege_denied;
for (x4=0;x4<=playerlist_last;x4++){ if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ tnpc2=(npc*)myobj2->more; if (txtsamewithoutcase(tnpc2->name,t2)){
//FOLLOWING LINE IS UNREQUIRED FOR GETIP
//if (((playerlist[x4]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)>((playerlist[tpl]->GNPCflags[privileges_index/16+40]>>((privileges_index%16)*2))&3)) goto privilege_denied2;
txtset(t4,"?"); t4->d2[0]=8;
txtadd(t4,t2);
txtadd(t4,"'s IP is ");
txtnumint(t,playerlist[x4]->GNPCflags[242]&255); txtadd(t4,t); txtadd(t4,".");
txtnumint(t,(playerlist[x4]->GNPCflags[242]>>8)&255); txtadd(t4,t); txtadd(t4,".");
txtnumint(t,(playerlist[x4]->GNPCflags[242]>>16)&255); txtadd(t4,t); txtadd(t4,".");
txtnumint(t,(playerlist[x4]->GNPCflags[242]>>24)&255); txtadd(t4,t);
NET_send(NETplayer,playerlist[tpl]->net,t4);
goto doneclmess;
}}}}
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No player named "); txtadd(t,t2); txtadd(t," is in Britannia! (check uppercase/lowercase)"); NET_send(NETplayer,playerlist[tpl]->net,t); goto doneclmess;
}//GETIP
txtset(t4,t2); txtucase(t4); txtset(t3,"QUITHOST"); if (txtsame(t4,t3)) {
if (myobj2=getprimarypartymemberobj(playerlist[tpl])){ tnpc2=(npc*)myobj2->more;}
x4=0;
while (admins[x4]) {
if (txtsame(tnpc2->name,admins[x4])){
u6orevive=255; seek(u6orevive_fh,0); put(u6orevive_fh,&u6orevive,1);
exitrequest=TRUE; exitrequest_noconfirm=TRUE; //exitrequest is required for the host + client version to quit properly.
for (x4=0;x4<=playerlist_last;x4++){
if (playerlist[x4]){ if (myobj2=getprimarypartymemberobj(playerlist[x4])){ /* send host quit message to all players */
txtset(t,"??"); t->d2[0]=250; t->d2[1]=1; NET_send(NETplayer,playerlist[x4]->net,t);
}}
}
goto doneclmess;
}
x4++;
if (x4==ADMINSMAX) {break;}
}
goto privilege_denied;
}
txtset(t4,t2); txtucase(t4); txtset(t3,"ME "); if (txtsearch(t4,t3)==1) goto anotherslashcommand;
txtset(t4,t2); txtucase(t4); txtset(t3,"RETURNBODY"); if (txtsearch(t4,t3)==1) goto anotherslashcommand;
txtsetchar(t,8); txtadd(t,"Unknown slash (/) command!"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
privilege_denied:
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Incorrect privileges!"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
privilege_denied2:
txtset(t,"?"); t->d2[0]=8; txtadd(t,"This player's privilege level is higher than yours!"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}//"/"
anotherslashcommand:
txtset(t2,t); txtucase(t2);
txtset(t3,"WHO");
if (txtsame(t2,t3)){
txtsetchar(t,8); //txtaddchar(t,255);
txtadd(t,inbritannia); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}
txtset(t3,"RESYNC"); if (txtsame(t2,t3)){
playerlist[tpl]->resync=1;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Resync request received."); NET_send(NETplayer,playerlist[tpl]->net,t);
// luteijn: let's see if this helps.
//send time
txtset(t2,"?"); t2->d2[0]=32;
txtset(t3,"12345678"); t3->dd[0]=btime2;
txtadd(t2,t3);
NET_send(NETplayer,tplayer->net,t2);
goto doneclmess;
}
txtset(t3,"/RETURNBODYFOLLOWERS"); if (txtsame(t2,t3)){
//IMPORTANT NOTE: RETURNBODYFOLLOWERS MAY CAUSE SOME VISUAL INVENTORY PROBLEMS
//ignore request if player is not dead
for (i2=1;i2<=7;i2++){
//locate player's body on resurrect list
for (i=0;i<=nresu;i++){
if (resu[i]){
if (resu_player[i]==playerlist[tpl]){
if (resu_partymember[i]==i2){
goto returnbodyfollowers_getresuindex;
}}}}
goto returnbodyfollowers_next;//unlisted!
returnbodyfollowers_getresuindex:
//remove current body
//IMPORTANT NOTE: IF A RECREATED OBJECT OF THE SAME TYPE USING SAME POINTER EXISTED THE FOLLOWING CHECK WOULD PRODUCE UNPREDICTABLE RESULTS
if (resu_body[i]->type==resu_body_type[i]){//object has not been released or reused
//check that resu_body[i] is not an mobj of a player
for (z=0;z<=playerlist_last;z++){ if (playerlist[z]){ if (playerlist[z]->net){
if (playerlist[z]->mobj==resu_body[i]) playerlist[z]->mobj=NULL;
}}}
OBJremove(resu_body[i]);
OBJrelease(resu_body[i]);
}//resu_body[i]->type==resu_body_type[i]
//create a new body at death spot
myobj=OBJnew();
myobj->type=resu_body_type[i];
myobj->info|=112;
OBJadd(resu_x[i],resu_y[i],myobj);
//link with new dead body
resu_body[i]=myobj;
returnbodyfollowers_next:;
}//i2
goto doneclmess;
}
txtset(t3,"/RETURNBODY"); if (txtsame(t2,t3)){
//IMPORTANT NOTE: RETURNBODY MAY CAUSE SOME VISUAL INVENTORY PROBLEMS
//ignore request if player is not dead
if (playerlist[tpl]->party[0]) goto doneclmess;
//locate player's body on resurrect list
for (i=0;i<=nresu;i++){
if (resu[i]){
if (resu_player[i]==playerlist[tpl]){
if (resu_partymember[i]==0){
goto returnbody_getresuindex;
}}}}
goto doneclmess;//unlisted!
returnbody_getresuindex:
//remove current body
//IMPORTANT NOTE: IF A RECREATED OBJECT OF THE SAME TYPE USING SAME POINTER EXISTED THE FOLLOWING CHECK WOULD PRODUCE UNPREDICTABLE RESULTS
if (resu_body[i]->type==resu_body_type[i]){//object has not been released or reused
//check that resu_body[i] is not an mobj of a player
for (z=0;z<=playerlist_last;z++){ if (playerlist[z]){ if (playerlist[z]->net){
if (playerlist[z]->mobj==resu_body[i]) playerlist[z]->mobj=NULL;
}}}
OBJremove(resu_body[i]);
OBJrelease(resu_body[i]);
}//resu_body[i]->type==resu_body_type[i]
//create a new body at death spot
myobj=OBJnew();
myobj->type=resu_body_type[i];
myobj->info|=112;
OBJadd(resu_x[i],resu_y[i],myobj);
//link with new dead body
resu_body[i]=myobj;
goto doneclmess;
}
if (x5&&(playerlist[tpl]->party[0]==NULL)) goto dglobal3;
if(myobj=playerlist[tpl]->party[0]){
txtset(t2,"KAL LOR");
if (txtsame(t,t2)){
tplayer=playerlist[tpl];
if ((tplayer->party[0]->x==368)&&(tplayer->party[0]->y==386)) goto help_skip;
if (tplayer->kallor) goto help_skip;
tplayer->kallor=32;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"\x022KAL LOR!\x022 (You will receive help in 30 seconds.)"); NET_send(NETplayer,tplayer->net,t);
help_skip:
goto doneclmess;
}
dglobal3:
static unsigned char me_message;
me_message=0;
txtset(t2,"/ME ");
txtset(t3,t); txtucase(t3); txtleft(t3,4);
if (txtsame(t3,t2)){
txtright(t,t->l-4);
if (t->l==0) goto doneclmess;
me_message=1;
}
if (x5) i3=SFnew(2047,1023); else i3=SFnew(myobj->x,myobj->y);
//i3 points to new sf
sf[i3].type=3; //message to users
if (playerlist[tpl]->party[0]){sf[i3].x=myobj->x; sf[i3].y=myobj->y-2;}
if (x5) { sf[i3].x=2047; sf[i3].y=1023; }
sf[i3].wait=2;
tnpc=NULL; if (playerlist[tpl]->party[0]) tnpc=(npc*)myobj->more;
if (playerlist[tpl]->party[0]){
sf[i3].more=tnpc->port;
//addnpcport2sf(unsigned long n,npc *tnpc)
//addnpcport2sf(i3,tnpc);
}else{
sf[i3].more=playerlist[tpl]->port;
}
static txt* inouttxt;
inouttxt=txtnew();
if (playerlist[tpl]->party[0]){
txtset(t2,tnpc->name);
}else{
txtset(t2,playerlist[tpl]->npcname);
}
txtset(inouttxt,"");
if (me_message){
txtaddcolouredname(inouttxt,t2,playerlist[tpl]);
txtadd(inouttxt," ");
txtadd(inouttxt,t);
}else{
txtadd(t2,":");
txtaddcolouredname(inouttxt,t2,playerlist[tpl]);
txtadd(inouttxt," \x022");
txtadd(inouttxt,t);
txtadd(inouttxt,"\x022");
}
sf[i3].p=inouttxt;
//txtset(t,"message ["); txtadd(t,inouttxt); txtadd(t,"] ("); txtnumint(t2,ett); txtadd(t,t2); txtadd(t,")"); txtfileout(t,log2);
if (tnpc){
txtset(t,"Message:");txtadd(t,tnpc->name); txtadd(t,":"); txtadd(t,inouttxt); LOGadd(t);
}
}
goto doneclmess;
} //6
if (t->d2[0]==34){//chat
playerlist[tpl]->typing=0;
playerlist[tpl]->idle=0;
if (playerlist[tpl]->party[0]==NULL) goto doneclmess;
if (myobj=(object*)playerlist[tpl]->talk_target->more){
//check if target is onscreen
//tpx=playerlist[tpl]->x-15; tpy=playerlist[tpl]->y-11; if (tpx<0) tpx=0; if (tpy<0) tpy=0; if (tpx>2016) tpx=2016; if (tpy>1000) tpy=1000;
getscreenoffset(playerlist[tpl]->x,playerlist[tpl]->y,&tpx,&tpy);
x=myobj->x; y=myobj->y;
if ((x>=tpx)&&(y>=tpy)&&(x<=(tpx+31))&&(y<=(tpy+23))){
x=x-tpx;
y=y-tpy;
txtright(t,t->l-1);
goto chat;
}//x,y check
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot chat to people you cannot see."); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}//->more
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Chatting to yourself again?"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;//no talk target or invalid talk target
}//34
if (t->d2[0]==7){ //text message to NPC/player (NPC message)
playerlist[tpl]->typing=0;
playerlist[tpl]->idle=0;
if (playerlist[tpl]->party[0]==NULL) goto doneclmess;
txtright(t,t->l-1);
x=t->ds[0]/32; y=t->ds[1]/32;
txtright(t,t->l-4);
chat:
//tpx=playerlist[tpl]->x-15; tpy=playerlist[tpl]->y-11; if (tpx<0) tpx=0; if (tpy<0) tpy=0; if (tpx>2016) tpx=2016; if (tpy>1000) tpy=1000;
getscreenoffset(playerlist[tpl]->x,playerlist[tpl]->y,&tpx,&tpy);
myobj=OBJfindlast(tpx+x,tpy+y); if (!myobj) myobj=OBJfindlastall(tpx+x,tpy+y);
if (myobj){
if (myobj->info&8) myobj=(object*)myobj->more;
static unsigned char npcmess_shrine=0;
npcmess_shrine=0;
if (myobj->type==OBJ_FORCE_FIELD){ //force field
myobj2=(object*)myobj->prev;
if (playerlist[tpl]->GNPCflags[3]&(1<<(myobj2->type>>10))) npcmess_shrine=190+(myobj2->type>>10);
}//force field
if ((myobj->type&1023)==OBJ_WISP) npcmess_shrine=199; //wisp
if ((myobj->type&1023)==OBJ_STOCKS){ if ((myobj->type>>11)&1){
npcmess_shrine=179; //man in stocks
}}
if ((myobj->type&1023)==OBJ_SHRINE){
myobj2=(object*)myobj->prev;
if ((myobj2->type&1023)==329) npcmess_shrine=198; //alter of singularity
}
if ((myobj->type&1023)==OBJ_GUARD){
if (myobj->info&4){ //crt
crt=(creature*)myobj->more;
if (crt->al==4) npcmess_shrine=200; //guard
}//4
}//382
if (npcmess_shrine) goto npcmess_shrine1;
//assume NPC type
if ((myobj->info&2)==0) goto talk_skipnullobject;
tnpc=(npc*)myobj->more;
if (tnpc==NULL) goto talk_skipnullobject;
//PRIVATE MESSAGE TO CLOSE PLAYER?
if (tnpc->player){
if (tnpc->player==playerlist[tpl]){ //send message to OUR OWN PARTY MEMBER
if (playerlist[tpl]->party[playerlist[tpl]->selected_partymember]!=myobj) goto talk_skipprivatemessage; //to SELECTED PARTY MEMBER
goto talk_privatemessage;
}
if (tnpc->player->party[0]){
if ((npc*)tnpc->player->party[0]->more==tnpc){ //party leader
//send a SPECIAL sfx buffer to a single player (can be tested by clicking on oneself)
talk_privatemessage:
static unsigned char me_message;
me_message=0;
txtset(t2,"/ME ");
txtset(t3,t); txtucase(t3); txtleft(t3,4);
if (txtsame(t3,t2)){
txtright(t,t->l-4);
me_message=1;
}
if (t->l){
tnpc2=(npc*)playerlist[tpl]->party[0]->more;
txtset(t4,tnpc2->name);
txtset(t3,"");
if (me_message){
txtaddcolouredname(t3,t4,playerlist[tpl]);
txtadd(t3," ");
txtadd(t3,t);
}else{
txtadd(t4,":");
txtaddcolouredname(t3,t4,playerlist[tpl]);
txtadd(t3," \x022");
txtadd(t3,t);
txtadd(t3,"\x022");
}
//txtadd(t3,": \x022");
//txtadd(t3,t);
//txtadd(t3,"\x022");
txtset(t,"?"); t->d2[0]=2;
txtset(t2,"??"); t2->ds[0]=1; txtadd(t,t2);
t2->ds[0]=3; txtadd(t,t2);
t2->ds[0]=2048; txtadd(t,t2);
t2->ds[0]=1023; txtadd(t,t2);
t2->ds[0]=t3->l; txtadd(t,t2);
t2->ds[0]=0; txtadd(t,t2); //unused
t2->ds[0]=tnpc2->port; txtadd(t,t2); //more=port
txtset(t2,"????"); t2->df[0]=2; txtadd(t,t2); //wait
txtadd(t,t3);
NET_send(NETplayer,tnpc->player->net,t);
if (tnpc->player==playerlist[tpl]){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Talking to yourself?"); NET_send(NETplayer,playerlist[tpl]->net,t);
}else{
NET_send(NETplayer,playerlist[tpl]->net,t);
}
}//t->l
goto doneclmess;
}
}
}
talk_skipprivatemessage:
if ((abs(myobj->x-playerlist[tpl]->party[0]->x)>8)||(abs(myobj->y-playerlist[tpl]->party[0]->y)>8)){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Out of range!"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}
/*
if (OBJcheckbolt(playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y,myobj->x,myobj->y)){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Blocked!"); NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}
*/
x4=1; //bedswap2
if (tnpc->schedule){ if (tnpc->schedule_i!=-1){ if (tnpc->schedule[tnpc->schedule_i].type==0x91){ x4=0;}}}
if ((tnpc->converse!=120)&&(tnpc->converse!=121)&&(tnpc->converse!=122)&&(tnpc->converse!=123)){//allow talking to sick warriors in Cove
if (x4==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No response!");
NET_send(NETplayer,playerlist[tpl]->net,t);
goto doneclmess;
}//No response!
}
//turn and face talker and begin "listening!"
if (myobj!=playerlist[tpl]->party[0]) OBJdir(myobj,playerlist[tpl]->party[0]->x,playerlist[tpl]->party[0]->y);
if (tnpc->player==NULL){ //not a party member!
if (tnpc->wait_walk<16.0f) tnpc->wait_walk=16.0f;
}
CONnpc2=tnpc; //only valid if #converse is derived from an NPC pointer!
npcmess_shrine1:
tplayer=playerlist[tpl];
//set as talk target!
VLNKremove(tplayer->talk_target); VLNKsremove(tplayer->talk_target);
tplayer->talk_target->more=myobj;
VLNKnew(tplayer->talk_target,myobj,(unsigned long)&tplayer->talk_target->more);
//RESET temp flags
ZeroMemory(&CONreg,sizeof(CONreg));
CONerr=0;
CONnumber=0;
CONqual=0xFFFFFFFF;
CONport=0xFFFFFFFF;
CONhousecost=0;
CONhouseinitialcost=0;
CONnumber=txtnum(t); //NUMBER
if (CONnumber<0) CONnumber=0;
if (CONnumber>32767) CONnumber=32767;
CONpartymember=0;
for (x2=0;x2<=7;x2++){
if (tplayer->party[x2]){
txtset(t2,t); txtucase(t2);
tnpc3=(npc*)tplayer->party[x2]->more;
txtset(t3,tnpc3->name); txtucase(t3);
if (txtsame(t2,t3)){
CONpartymember=x2+1; //(1-8)
}
}
}
txtset(t9,t);
if (t->l==0) txtset(t,"look"); //default
//remove strange characters from t!
npccon_cull:
for (x2=0;x2<t->l;x2++){
x3=t->d2[x2];
if( (x3<48) || ((x3>57)&&(x3<65)) || ((x3>90)&&(x3<97)) || (x3>122) ){
txtset(t2,t);
txtleft(t,x2);
txtright(t2,t2->l-x2-1);
txtadd(t,t2);
goto npccon_cull;
}
}
txtlcase(t);
//NPC converse interpreter
//<-NPC's object(myobj) + <-*player(tplayer)
//if (t->l<=2){
//txtset(t,"unknown");
//}
//next instruction
static bool lookchk=FALSE;
lookchk=FALSE;
if (npcmess_shrine) {x9=npcmess_shrine; goto npcmess_shrine2;}
tnpc=(npc*)myobj->more;
x9=tnpc->converse;
if (x9==255) x9=0; //*Dupre
npcmess_shrine2:
CONnpc=x9;
x=npci[CONnpc]; //first instruction index
//before checking first instruction, check for in-party commands
if (!npcmess_shrine){
if (tnpc->player==tplayer){ //partymember
/*
i3=0;
txtset(t2,"dont"); if (txtsearch(t,t2)) i3=1;
txtset(t2,"stop"); if (txtsearch(t,t2)) i3=1;
txtset(t2,"not"); if (txtsearch(t,t2)) i3=1;
if (i3){
txtset(t2,"poti");
if (txtsearch(t,t2)){
txtset(t2,"yell");
if (txtsearch(t,t2)){
if (tnpc->command&1) tnpc->command-=1;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I won't use yellow potions.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
txtset(t2,"red");
if (txtsearch(t,t2)){
if (tnpc->command&2) tnpc->command-=2;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I won't use red potions.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
}//"poti"
txtset(t2,"eat");
if (txtsearch(t,t2)){
if (tnpc->command&4) tnpc->command-=4;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I'll refrain from eating.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
txtset(t2,"cast");
if (txtsearch(t,t2)){
txtset(t2,"cure");
if (txtsearch(t,t2)){
if (tnpc->command&32) tnpc->command-=32;
if (tnpc->command&64) tnpc->command-=64;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I won't cast cure.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
txtset(t2,"heal");
if (txtsearch(t,t2)){
if (tnpc->command&8) tnpc->command-=8;
if (tnpc->command&16) tnpc->command-=16;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I won't cast heal spells.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
}//"cast"
}//negative
txtset(t2,"poti");
if (txtsearch(t,t2)){
txtset(t2,"yell");
if (txtsearch(t,t2)){
tnpc->command|=1;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I shall use yellow potions if heavily wounded.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
txtset(t2,"red");
if (txtsearch(t,t2)){
tnpc->command|=2;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I shall use red potions if poisoned.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
}//"poti"
txtset(t2,"eat");
if (txtsearch(t,t2)){
tnpc->command|=4;
static txt *txttmp0;
txttmp0=txtnew();
txtset(txttmp0,"\x022I shall eat or drink when hungry.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
txtset(t2,"cast");
if (txtsearch(t,t2)){
i3=0;
txtset(t2,"all"); if (txtsearch(t,t2)) i3=1;
txtset(t2,"ever"); if (txtsearch(t,t2)) i3=1;
txtset(t2,"part"); if (txtsearch(t,t2)) i3=1;
txtset(t2,"cure");
if (txtsearch(t,t2)){
if (!i3) tnpc->command|=32; else tnpc->command|=64;
static txt *txttmp0;
txttmp0=txtnew();
if (!i3) txtset(txttmp0,"\x022I shall cast cure if poisoned.\x022"); else txtset(txttmp0,"\x022I shall cast cure if anyone in our party is poisoned.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
txtset(t2,"heal");
if (txtsearch(t,t2)){
if (!i3) tnpc->command|=8; else tnpc->command|=16;
static txt *txttmp0;
txttmp0=txtnew();
if (!i3) txtset(txttmp0,"\x022I shall cast heal spells if heavily wounded.\x022"); else txtset(txttmp0,"\x022I shall cast heal spells if anyone in our party is heavily wounded.\x022");
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
sf[i3].more=tnpc->port;
//addnpcport2sf(i3,tnpc);
sf[i3].p=txttmp0;
goto doneclmess;
}
}//"cast"
*/
if (tnpc->converse==NULL) goto talk_skipnullobject;
}//tplayer
}//!npcmess_shrine (->npc)
nextinstruction:
if (npcbin[x].l1==1){ //if=keyword goto (ifkey)
//long txtsearch(txt*t,txt*t2);
txtNEWLEN(t2,npcbin[x].l3);
memcpy(t2->d2,&npcinf[npcbin[x].l2],npcbin[x].l3);
ifkey_next:
txtset(t4,t2);
txtset(t3,",");
if (x2=txtsearch(t2,t3)){
txtleft(t4,x2-1);
txtright(t2,t2->l-x2);
}else{
txtset(t2,"");
}
//txtset(t3," "); txtadd(t3,t4); txtset(t4,t3); //add a space before the keyword
//txtset(t5," "); txtadd(t5,t);
if (txtsearch(t,t4)){ //t2=keyword string
txtset(t3,"look"); if (txtsearch(t4,t3)) lookchk=TRUE;
x++; goto nextinstruction;
}
if (t2->l) goto ifkey_next;
//it is possible t2 is a truncated version of t if it is 4 characters long
//if (t2->l==4){ //short keyword
//txtset(t3,t); if (t3->l>4) txtleft(t3,4);
//if (txtsearch(t2,t3)){
//x++; goto nextinstruction;
//}
//}
x=npcbin[x].l4; goto nextinstruction;
}
if ((npcbin[x].l1==2)||(npcbin[x].l1==22)){ //display txt and exit || display txt and DONT exit
i3=SFnew(myobj->x,myobj->y); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=myobj->x;
sf[i3].y=myobj->y-2;
sf[i3].wait=5;
tnpc=(npc*)myobj->more;
if (npcmess_shrine==0){
//GPFGPF
sf[i3].more=tnpc->port; //portrait upper byte may be used to store more information (or it could be stored in the message)
//addnpcport2sf(i3,tnpc);
}else{
sf[i3].more=187; //blank!
if (npcmess_shrine==199) sf[i3].more=191; //wisp
if (npcmess_shrine==179) sf[i3].more=180; //man in stocks
if (npcmess_shrine==200) sf[i3].more=192; //guard
}
if (CONport!=0xFFFFFFFF) sf[i3].more=CONport;
CONport=0xFFFFFFFF;
static txt* inouttxt2;
inouttxt2=txtnew();
txtNEWLEN(inouttxt2,npcbin[x].l3);
memcpy(inouttxt2->d2,&npcinf[npcbin[x].l2],npcbin[x].l3);
if (lookchk){
txtset(t2,"look");
if (txtsame(t,t2)){
txtset(t2,"You see ");
txtadd(t2,inouttxt2);
txtset(inouttxt2,t2);
lookchk=0;
}
}
txtset(t2,"ambidextrous!"); //ambidextrous (FIX: M'sieur Loubet training +1 DEX)
if (txtsearch(inouttxt2,t2)){
tnpc2=(npc*)tplayer->party[0]->more;
tnpc2->d++;
tnpc2->upflags|=1;
}
insert_txt:
/*
if ((tnpc->i>=tnpc->s)&&(tnpc->i>=tnpc->d)) myobj->type=378; //i
if ((tnpc->d>=tnpc->s)&&(tnpc->d>=tnpc->i)) myobj->type=386; //d
if ((tnpc->s>=tnpc->d)&&(tnpc->s>=tnpc->i)) myobj->type=376; //s
if ((tnpc->i>tnpc->s)&&(tnpc->d>tnpc->s)) myobj->type=377; //i+d
txtset(t2,"$NAME"); //$NAME
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-2);
//txtnumint(t4,CONreg[0]); txtadd(t2,t4);
txtadd(t2,
txtadd(t2,t3); txtset(inouttxt2,t2);
goto insert_txt;
}
*/
//CONnpc=tnpc; //only valid if #converse is derived from an NPC pointer!
txtset(t2,"$RATE"); //$RATE
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-4);
//assume +3 per level, anything above min threshold costs double!!!
x2=37+3*CONnpc2->lev;
if ((CONnpc2->s+CONnpc2->d+CONnpc2->i)>x2) txtadd(t2,"24"); else txtadd(t2,"8");
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$SDI"); //$SDI
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-3);
txtadd(t2,"(str:");
txtnumint(t4,CONnpc2->s); txtadd(t2,t4);
txtadd(t2,", dex:");
txtnumint(t4,CONnpc2->d); txtadd(t2,t4);
txtadd(t2,", int:");
txtnumint(t4,CONnpc2->i); txtadd(t2,t4);
txtadd(t2,")");
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$CLASS"); //$CLASS
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-5);
txtset(t4,"ranger");
if ((CONnpc2->i>CONnpc2->s)&&(CONnpc2->i>CONnpc2->d)) {txtset(t4,"mage"); goto gotclass;}
if ((CONnpc2->d>CONnpc2->s)&&(CONnpc2->d>CONnpc2->i)) {txtset(t4,"bard"); goto gotclass;}
if ((CONnpc2->s>CONnpc2->d)&&(CONnpc2->s>CONnpc2->i)) {txtset(t4,"fighter"); goto gotclass;}
if ((CONnpc2->s>CONnpc2->d)&&(CONnpc2->i>CONnpc2->d)) {txtset(t4,"paladin"); goto gotclass;}
if ((CONnpc2->s>CONnpc2->i)&&(CONnpc2->d>CONnpc2->i)) {txtset(t4,"tinker"); goto gotclass;}
if ((CONnpc2->d>CONnpc2->s)&&(CONnpc2->i>CONnpc2->s)) {txtset(t4,"druid"); goto gotclass;}
x2=CONnpc2->s+CONnpc2->d+CONnpc2->i;
if (x2<=52) txtset(t4,"shepard");
gotclass:
/*
Honesty (Truth - Mage) i3
Compassion (Love - Bard) d3
Valor (Courage - Fighter) s3
Justice (Truth and Love - Druid) s1 i1
Sacrifice (Love and Courage - Tinker) s1 d1
Honor (Truth and Courage - Paladin) d1 i1
Spirituality (Truth and Love and Courage - Ranger) s1 d1 i1
Humility (None - Shepherd) N/A
*/
txtadd(t2,t4); txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$NAME"); //$NAME
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-4);
txtadd(t2,CONnpc2->name); txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$HIRE"); //$HIRE
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-4);
txtadd(t2,"24"); txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$V1"); //$V1
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-2);
txtnumint(t4,CONreg[1]); txtadd(t2,t4); txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$V0"); //$V0
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-2);
txtnumint(t4,CONreg[0]); txtadd(t2,t4); txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$PARTYMEMBER"); //$PARTYMEMBER party member's name
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-11);
tnpc2=(npc*)tplayer->party[CONpartymember-1]->more;
txtadd(t2,tnpc2->name);
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$P"); //$P name
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-1);
tnpc2=(npc*)tplayer->party[0]->more;
txtadd(t2,tnpc2->name);
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$Y"); //$Y name (originally of talking party member)
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-1);
tnpc2=(npc*)tplayer->party[0]->more;
txtadd(t2,tnpc2->name);
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$G"); //$G
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-1);
if (tplayer->male_female) txtadd(t2,"milady"); else txtadd(t2,"milord");
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$T"); //$T morning afternoon evening
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-1);
if (btime<12) txtadd(t2,"morning");
if ((btime>=12)&&(btime<=18)) txtadd(t2,"afternoon");
if (btime>18) txtadd(t2,"evening");
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
txtset(t2,"$Z"); //$Z
if (x2=txtsearch(inouttxt2,t2)){
txtset(t2,inouttxt2); txtleft(t2,x2-1);
txtset(t3,inouttxt2); txtright(t3,inouttxt2->l-x2-1);
txtadd(t2,t9);
txtadd(t2,t3);
txtset(inouttxt2,t2);
goto insert_txt;
}
sf[i3].p=inouttxt2;
if (npcbin[x].l1==22) {x++; goto nextinstruction;}
}
if (npcbin[x].l1==3){ //jmp
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==4){ //=
CON_sv(npcbin[x].l2,npcbin[x].l3);
x++; goto nextinstruction;
}
if (npcbin[x].l1==5){ //if=
x3=CON_gv(npcbin[x].l3);
x2=CON_gv(npcbin[x].l2);
if (x2==x3){ //=
x++; goto nextinstruction;
}
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==6){ //item
x2=CON_gv(npcbin[x].l2); //type
x3=CON_gv(npcbin[x].l3); //info/qty
myobj4=myobj; //backup!
tnpc2=(npc*)tplayer->party[0]->more;
myobj3=OBJnew(); myobj3->type=x2; myobj3->more2=x3;
if ((tnpc2->wt+WTfind(myobj3))<=tnpc2->wt_max){
additemroot(tnpc2,myobj3);
} //weight
tnpc2->upflags|=32; //inv
myobj=myobj4; //<-backup
x++; goto nextinstruction;
}
//buy/give
if (npcbin[x].l1==7){ //buy
x2=CON_gv(npcbin[x].l2); //type
x3=CON_gv(npcbin[x].l3); //number of items (1-?) *0 is invalid
x4=CON_gv(npcbin[x].l4); //gold
myobj4=myobj; //backup!
tnpc2=(npc*)tplayer->party[0]->more;
//check gold
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
y7=0; y8=0;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==88){ //gold
if (y7<x4){
if (OBJlist_list[y6]->info&128) y8=1;
}
y7+=OBJlist_list[y6]->more2;
}
}
if (y7<x4) {CONerr=1; goto buy_nogold;} //not enough gold
if (CONqual!=0xFFFFFFFF){
if (CONqual&16384){ //ignore stolen gold!
CONqual-=16384;
if (y8) {CONerr=1; goto buy_nogold;} //not enough gold
}
}
if (x2==0) goto buy_removegold;
buy_newitem:
myobj3=OBJnew(); myobj3->type=x2;
if (obji[sprlnk[x2&1023]+(x2>>10)].flags&4096) myobj3->more2=1; //temp =1 to find weight of single object
f=WTfind(myobj3)*x3;
myobj3->more2=0; //*can override
if (CONqual!=0xFFFFFFFF){
if (CONqual&32768) {CONqual-=32768; myobj3->info|=256;} //quest
myobj3->more2=CONqual;
}
if (obji[sprlnk[x2&1023]+(x2>>10)].flags&4096){
myobj3->more2=x3;
x3=1;
}
//x3 now equals number of objects to allocate
if (myobj3->info&256) goto questitem_skipweightcheck2;
if ((tnpc2->wt+f)<=tnpc2->wt_max){
questitem_skipweightcheck2:
if (y8) myobj3->info|=128;
stealing(tplayer,myobj3);
ENHANCEnewn(myobj3,8,8);
myobj6=myobj3;
if (myobj6->type==76){
if (!tnpc2->neck) goto amuletofsubmission0;
myobj3=tnpc2->neck;
}
additemroot(tnpc2,myobj3);
x3--;
if (x3) goto buy_newitem;
if (myobj6->type==76){
amuletofsubmission0:
tnpc2->neck=myobj6;
tnpc2->upflags|=64;
}
//buy horse papers
if (myobj3->type==448){
if (CONnpc==25) movernew(430,280,441,MOVERNEW_FLAG_NORESPAWN);
if (CONnpc==78) movernew(430,412,802,MOVERNEW_FLAG_NORESPAWN);
((creature*)MOVERNEW_OBJECT->more)->flags|=128;
((creature*)MOVERNEW_OBJECT->more)->al=0;
static long horseval;
//locate tpl index
((creature*)MOVERNEW_OBJECT->more)->respawn_y=0xFFFF;
for (horseval=0;horseval<=playerlist_last;horseval++){ if (playerlist[horseval]){
if (playerlist[horseval]==tplayer){
((creature*)MOVERNEW_OBJECT->more)->respawn_y=horseval;
goto buyhorse_foundtpl;
}
}}
buyhorse_foundtpl:
//set initial horse status (races won, food, horseshoes)
horseval=0;
if (((long)(rnd*2))==0){
buyhorseaddracewon:
if (horseval<15){
if (((long)(rnd*2))==0) {horseval++; goto buyhorseaddracewon;}
}
}
if (CONnpc==25) ((creature*)MOVERNEW_OBJECT->more)->respawn_x=horseval+(2<<4)+(1<<6);
if (CONnpc==78) ((creature*)MOVERNEW_OBJECT->more)->respawn_x=horseval+(1<<4)+(0<<6);
myobj3->more=MOVERNEW_OBJECT;
//the fact that this is a player's horse needs to be set somewhere...
}//buy horse papers
//buy skiff/ship?
if ((myobj3->type&1023)==149){
if (CONqual==0){
myobj5=OBJnew(); myobj5->type=412+9*1024;
if (CONnpc==26) OBJadd(316,441,myobj5); //arty
if (CONnpc==119) OBJadd(592,622,myobj5); //fentrissa
if (CONnpc==51) OBJadd(164,872,myobj5); //peer
if (CONnpc==70) OBJadd(603,119,myobj5); //trebor
static mlobj *mmyobj; //array size varies
mmyobj=(mlobj*)malloc(sizeof(object*)*5);
myobj5->more=mmyobj;
myobj=OBJnew(); mmyobj->obj[0]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[1]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[2]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[3]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj=OBJnew(); mmyobj->obj[4]=myobj; myobj->info|=8; myobj->type=myobj5->type; myobj->more=(object*)myobj5; OBJadd(myobj5->x,myobj5->y,myobj);
myobj3->more=myobj5; //deed->ship
OBJmove_allow=TRUE;
OBJmove2(myobj5,myobj5->x,myobj5->y+1);
OBJmove2(myobj5,myobj5->x,myobj5->y-1);
OBJmove_allow=FALSE;
}//CONqual
if (CONqual==1){
myobj5=OBJnew(); myobj5->type=414;
if (CONnpc==26) OBJadd(316,441,myobj5); //arty
if (CONnpc==119) OBJadd(592,622,myobj5); //fentrissa
if (CONnpc==51) OBJadd(164,872,myobj5); //peer
if (CONnpc==70) OBJadd(603,119,myobj5); //trebor
myobj3->info|=(1<<9);
myobj3->more=myobj5; //deed->skiff
}//CONqual
}//149
tnpc2->upflags|=32; //inv
buy_removegold:
//remove gold!
//recreate OBJlist
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==88){ //gold
myobj5=OBJlist_list[y6];
x7=myobj5->more2; //25
x7-=x4; //25-10=10
x4-=myobj5->more2; //=-15
//txtnumint(t5,x4);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
if (x7<=0){
OBJremove(myobj5);
OBJrelease(myobj5);
}else{
myobj5->more2=x7;
}
if (x4<=0) goto buy_gotgold;
}
}
buy_gotgold:
//update ALL! party inventory windows
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
tnpc3->upflags|=32; //inv
}} //!=NULL,x6
}else{CONerr=2;} //weight
buy_nogold:
CONqual=0xFFFFFFFF; //reset
myobj=myobj4; //<-backup
x++; goto nextinstruction;
}
if (npcbin[x].l1==8){ //if!=
x3=CON_gv(npcbin[x].l3);
x2=CON_gv(npcbin[x].l2);
if (x2!=x3){ //=
x++; goto nextinstruction;
}
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==9){ //+
CON_sv(npcbin[x].l2,CON_gv(npcbin[x].l2)+CON_gv(npcbin[x].l3));
x++; goto nextinstruction;
}
if (npcbin[x].l1==10){ //-
CON_sv(npcbin[x].l2,CON_gv(npcbin[x].l2)-CON_gv(npcbin[x].l3));
x++; goto nextinstruction;
}
if (npcbin[x].l1==11){ //*
CON_sv(npcbin[x].l2,CON_gv(npcbin[x].l2)*CON_gv(npcbin[x].l3));
x++; goto nextinstruction;
}
if (npcbin[x].l1==12){ //div /
CON_sv(npcbin[x].l2,CON_gv(npcbin[x].l2)/CON_gv(npcbin[x].l3));
x++; goto nextinstruction;
}
if (npcbin[x].l1==13){ //ifitem
tnpc2=(npc*)tplayer->party[0]->more;
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
y7=0; //count
for(y6=0;y6<x5;y6++){
if (CON_gv(npcbin[x].l2)==185){
if ((OBJlist_list[y6]->type&1023)==185) goto ifitem_clothtype;
}
if (OBJlist_list[y6]->type==CON_gv(npcbin[x].l2)){
ifitem_clothtype:
if ((CONqual==0xFFFFFFFF)||(CONqual==OBJlist_list[y6]->more2)){
if ((OBJlist_list[y6]->info&32768)==0){//skip if not for sale
if (obji[sprlnk[OBJlist_list[y6]->type&1023]+(OBJlist_list[y6]->type>>10)].flags&4096) y7+=OBJlist_list[y6]->more2; else y7++;
}
}//qual
}
}
CONqual=0xFFFFFFFF; //reset
if (y7>=CON_gv(npcbin[x].l3)){ //=
x++; goto nextinstruction;
}
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==14){ //sell
x2=CON_gv(npcbin[x].l2); //type
x3=CON_gv(npcbin[x].l3); //info/qty
if (x3==0) x3=1;
x4=CON_gv(npcbin[x].l4); //gold
myobj4=myobj; //backup!
tnpc2=(npc*)tplayer->party[0]->more;
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
y7=0; //quantity
for(y6=0;y6<x5;y6++){
if (x2==185){
if ((OBJlist_list[y6]->type&1023)==185) goto sell_clothtype;
}
if (OBJlist_list[y6]->type==x2){ //has item?
sell_clothtype:
if ((CONqual==0xFFFFFFFF)||(CONqual==OBJlist_list[y6]->more2)){
if ((OBJlist_list[y6]->info&32768)==0){//skip if not for sale
if (obji[sprlnk[OBJlist_list[y6]->type&1023]+(OBJlist_list[y6]->type>>10)].flags&4096) y7+=OBJlist_list[y6]->more2; else y7++;
}
}//qual
}
}
if (y7<x3) {CONerr=1; goto sell_noitem;}
//remove item!
y8=0;
for(y6=0;y6<x5;y6++){
if (x2==185){
if ((OBJlist_list[y6]->type&1023)==185) goto sell_clothtype2;
}
if (OBJlist_list[y6]->type==x2){ //item->type
sell_clothtype2:
if ((CONqual==0xFFFFFFFF)||(CONqual==OBJlist_list[y6]->more2)){
if ((OBJlist_list[y6]->info&32768)==0){//skip if not for sale
myobj5=OBJlist_list[y6];
if (myobj5->info&128) y8=1; //stealing!
if (obji[sprlnk[OBJlist_list[y6]->type&1023]+(OBJlist_list[y6]->type>>10)].flags&4096) x8=OBJlist_list[y6]->more2; else x8=1;
x7=x8;
x7-=x3;
x3-=x8;
if (x7<=0){
OBJremove(myobj5);
OBJrelease(myobj5);
}else{
myobj5->more2=x7;
}
if (x3<=0) goto sell_gotitem;
}//not for sale
}//qual
}//type
}//y6
sell_gotitem:
if (x4){
myobj3=OBJnew(); myobj3->type=88; myobj3->more2=x4; //gold
if (y8) myobj3->info|=128; //stealing!
stealing(tplayer,myobj3);
additemroot(tnpc2,myobj3);
}//x4
tnpc2->upflags|=32; //inv
//update ALL party inventory windows
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
tnpc3->upflags|=32; //inv
}} //!=NULL,x6
sell_noitem:
CONqual=0xFFFFFFFF; //reset
myobj=myobj4; //<-backup
x++; goto nextinstruction;
}
if (npcbin[x].l1==15){ //if<
x3=CON_gv(npcbin[x].l3); x2=CON_gv(npcbin[x].l2);
if (x2<x3){ x++; goto nextinstruction; }
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==16){ //if>
x3=CON_gv(npcbin[x].l3); x2=CON_gv(npcbin[x].l2);
if (x2>x3){ x++; goto nextinstruction; }
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==17){ //if<=
x3=CON_gv(npcbin[x].l3); x2=CON_gv(npcbin[x].l2);
if (x2<=x3){ x++; goto nextinstruction; }
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==18){ //if>=
x3=CON_gv(npcbin[x].l3); x2=CON_gv(npcbin[x].l2);
if (x2>=x3){ x++; goto nextinstruction; }
x=npcbin[x].l4; goto nextinstruction;
}
//join error messages
//1 already in party
//2 party is full
//3 in different party
//leave errors
//1 not in party!
//2 not near home
if (npcbin[x].l1==19){ //join!
if (tnpc->player){
if (tplayer==tnpc->player){CONerr=1; goto joined;} //(1)already in party
CONerr=3; goto joined; //(3)in different party
}
for (x2=1;x2<=7;x2++){
if (tplayer->party[x2]==NULL){
//check no dead player is assigned to this slot
for (x3=0;x3<=nresu;x3++){
if (resu[x3]){
if (resu_player[x3]==tplayer){
if (resu_partymember[x3]==x2) goto joinblocked_indexused;
}}}
tplayer->party[x2]=myobj;
tnpc->player=tplayer;
tnpc->order=1;
tnpc->follow=tplayer->party[0];
tnpc->upflags|=1; //all
tnpc->wait_walk=0;
myobj->info&=(32655); //remove temp flag 32767-112
for (i=0;i<=HIRELINGS_MAX -1;i++){
if (hirl_obj[i]==myobj) {
hirl_obj[i]=0; //if in hireling list remove
}
}
goto joined;
}
joinblocked_indexused:;
}
CONerr=2; //party is full
joined:;
x++; goto nextinstruction;
}
if (npcbin[x].l1==27){ //leave!
if (tnpc->player!=tplayer) {CONerr=1; goto leavefinished;} //(1)not in party
for (x2=0;x2<=7;x2++){
if (tplayer->party[x2]){
if ((npc*)tplayer->party[x2]->more==tnpc){
tnpc->pathn=0; //NULL autopath
for (x3=0;x3<=31;x3++){
if (tnpc->schedule[x3].hour!=255){
//x4=pathfind(tnpc->path,tplayer->party[x2]->x,tplayer->party[x2]->y,tnpc->schedule[x3].x,tnpc->schedule[x3].y,NULL);
//if ((x4>0)&&(x4<=64)) goto leavepathok;
WPF_NEXTTO=1; WPF_OBJECT=tplayer->party[x2]; wpf_pathfind(tnpc->path,tplayer->party[x2]->x,tplayer->party[x2]->y,tnpc->schedule[x3].x,tnpc->schedule[x3].y,64,0,4);
if (WPF_RETURN==WPF_PATHFOUND) goto leavepathok;
}//!=255
}//x3
CONerr=2; goto leavefinished; //(2)not near home
leavepathok:
horsedismount(tplayer->party[x2]);
leaveitems:
if (myobj3=(object*)tnpc->items->more){
OBJremove(myobj3);
OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);
goto leaveitems;
}
if (myobj3=tnpc->helm){ tnpc->helm=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
if (myobj3=tnpc->neck){ tnpc->neck=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
if (myobj3=tnpc->wep_left){
if (myobj3->type==(90+1024)) myobj3->type=90;
tnpc->wep_left=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
if (myobj3=tnpc->wep_right){
if (myobj3->type==(90+1024)) myobj3->type=90;
tnpc->wep_right=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
if (myobj3=tnpc->armour){ tnpc->armour=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
if (myobj3=tnpc->ring_left){ tnpc->ring_left=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
if (myobj3=tnpc->ring_right){ tnpc->ring_right=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
if (myobj3=tnpc->boots){ tnpc->boots=NULL; OBJadd(tplayer->party[x2]->x,tplayer->party[x2]->y,myobj3);}
tnpc->baseitem=tnpc->items; tnpc->baseitem_offset=0;
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[x2],tplayer->party[x2]->x,tplayer->party[x2]->y+1);
OBJmove2(tplayer->party[x2],tplayer->party[x2]->x,tplayer->party[x2]->y-1);
OBJmove_allow=FALSE;
//send message stating the NPC has died/left
txtset(t5,"??"); t5->d2[0]=252; t5->d2[1]=x2; NET_send(NETplayer,tplayer->net,t5);
if ((tnpc->converse)&&(tnpc->converse==201)) { //not core npc
tplayer->party[x2]->info|=112; //set as temp item
}
tplayer->party[x2]=NULL;
tplayer->selected_partymember=0;
tnpc->player=NULL;
tnpc->order=2; //follow schedule
tnpc->follow=NULL;
goto leavefinished;
}//==tnpc
}//->party[x2]
}//x2
leavefinished:
x++; goto nextinstruction;
}
if (npcbin[x].l1==20){ //cure!
if (CONpartymember==0){
for (x2=0;x2<=7;x2++){
if (tplayer->party[x2]){
tnpc3=(npc*)tplayer->party[x2]->more;
tnpc3->flags&=(65535-1); //remove poisoned flag
tnpc3->upflags|=2;
}
}//x2
}else{//!=0
tnpc3=(npc*)tplayer->party[CONpartymember-1]->more;
if ((tnpc3->flags&1)==0) CONerr=1;
tnpc3->flags&=(65535-1); //remove poisoned flag
tnpc3->upflags|=2;
}
x++; goto nextinstruction;
}
if (npcbin[x].l1==21){ //heal!
if (CONpartymember==0){
for (x2=0;x2<=7;x2++){
if (tplayer->party[x2]){
tnpc3=(npc*)tplayer->party[x2]->more;
tnpc3->hp=tnpc3->hp_max;
tnpc3->mp=tnpc3->mp_max;
tnpc3->upflags|=(2+4);
}
}//x2
}else{//!=0
tnpc3=(npc*)tplayer->party[CONpartymember-1]->more;
if (tnpc3->hp==tnpc3->hp_max){
if (tnpc3->mp==tnpc3->mp_max){
CONerr=1; //ERR_ALREADY
}
}
tnpc3->hp=tnpc3->hp_max;
tnpc3->mp=tnpc3->mp_max;
tnpc3->upflags|=(2+4);
}
x++; goto nextinstruction;
}
if (npcbin[x].l1==23){ //ifparty
txtNEWLEN(t2,npcbin[x].l3);
memcpy(t2->d2,&npcinf[npcbin[x].l2],npcbin[x].l3);
for (x2=1;x2<=7;x2++){
if (tplayer->party[x2]){
tnpc3=(npc*)tplayer->party[x2]->more;
txtset(t3,tnpc3->name); txtlcase(t3);
if (txtsame(t2,t3)){
x++; goto nextinstruction;
}//txtsame
}
}//x2
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==24){ //levelup!
CONerr=1;
if (CONpartymember){ if (tplayer->party[CONpartymember-1]){ //valid value?
tnpc3=(npc*)tplayer->party[CONpartymember-1]->more;
//entitled to levelup?
x3=(800<<(tnpc3->lev-1)); //required xp to level
if (tnpc3->exp>=x3){ //levelup
tnpc3->lev++;
tnpc3->upflags|=1;
tnpc3->hp_max=tnpc3->lev*30;
tnpc3->s+=npcbin[x].l2; tnpc3->d+=npcbin[x].l3; tnpc3->i+=npcbin[x].l4;
tnpc3->wt_max=tnpc3->s*4*100;
tnpc3->wt2_max=tnpc3->s*50;
if (CONpartymember==1){
tnpc3->mp_max=tnpc3->i*2;
}else{
tnpc3->mp_max=get_mp_max(tnpc3->i);
//tnpc3->wt_max/=2;//halve wt_max for non-primary partymember
tnpc3->wt_max=tnpc3->s*3*100;
}
CONerr=0;
inbritanniacheck();
}//x3
}}
x++; goto nextinstruction;
}
if (npcbin[x].l1==25){ //rest!
if (tplayer->rest==0) tplayer->rest=32;
x++; goto nextinstruction;
}
if (npcbin[x].l1==26){ //resurrect!
//scan inventory of all players for bodies & crossreference these with ressurect lists
CONerr=1;
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if ((OBJlist_list[y6]->type&1023)==339){ //dead body
CONerr=2;
//scan resurrect list
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_body[i3]==OBJlist_list[y6]){
/*
object *resu[65536]; //object
object *resu_body[65536]; //dead body object
float resu_wait[65536]; //time until object automatically resurrected
player *resu_player[65536]; //player object belongs to
unsigned char resu_partymember[65536]; //party member index
long nresu=-1;
*/
if (resu_player[i3]){ //has a player pointer
////resu_player[i3]->party[0]=resu[i3]; //assume current player
resu_player[i3]->party[resu_partymember[i3]]=resu[i3];
//tnpc2=(npc*)resu[i3]->more; tnpc2->exp-=int(tnpc2->exp/4);
if (resu_partymember[i3]==0){
resu_player[i3]->GNPCflags[25]=0; //used insurance!
for (x4=1;x4<=7;x4++){
if (resu_player[i3]->party[x4]){
tnpc3=(npc*)resu_player[i3]->party[x4]->more; tnpc3->upflags=1;
OBJmove_allow=TRUE;
OBJmove2(resu_player[i3]->party[x4],tplayer->party[tplayer->selected_partymember]->x,tplayer->party[tplayer->selected_partymember]->y); //place party on the map
OBJmove_allow=FALSE;
}
}//x4
}
OBJmove_allow=TRUE;
OBJmove2(resu[i3],tplayer->party[tplayer->selected_partymember]->x,tplayer->party[tplayer->selected_partymember]->y); //place avatar on the map
OBJmove_allow=FALSE;
OBJremove(OBJlist_list[y6]); //remove body
tnpc3=(npc*)resu[i3]->more;
resu[i3]=NULL;
if (resu_partymember[i3]==0){
txtset(t5,"?"); t5->d2[0]=8; txtadd(t5,"A voice in the darkness intones, \x022"); txtadd(t5,"DOMAN THIXUS ANRETU!\x022"); NET_send(NETplayer,resu_player[i3]->net,t5);
txtset(t5,"?"); t5->d2[0]=8; txtadd(t5,tnpc3->name); txtadd(t5," resurrected by healer.");
for (x2=0;x2<=playerlist_last;x2++){ //create and send UPDATE message
if (playerlist[x2]){ //current player
if (playerlist[x2]->net!=NULL){ //net connection available
if (playerlist[x2]->party[0]){
if (playerlist[x2]!=resu_player[i3]){
NET_send(NETplayer,playerlist[x2]->net,t5);
}}}}}
}
inbritanniacheck();
CONerr=0;
goto resurrect_success;
}//player
}//resu_body==obj
}//resu
}//i
}//339
}
resurrect_success:
x++; goto nextinstruction;
}
if (npcbin[x].l1==28){ //ifnpc
for (y2=myobj->y-8;y2<=(myobj->y+8);y2++){ for (x2=myobj->x-8;x2<=(myobj->x+8);x2++){
if (myobj3=OBJfindlast(x2,y2)){
if (myobj3->info&2){
tnpc3=(npc*)myobj3->more;
if (tnpc3->converse==npcbin[x].l2){x++; goto nextinstruction;}
}//2
}//myobj3
}}//x,y
x=npcbin[x].l4; goto nextinstruction;
}
if (npcbin[x].l1==29){ //buyhouse!
if (tplayer->party[0]){
tnpc3=(npc*)tplayer->party[0]->more;
//if= ERROR,1/txt He rustles through his papers.\"You must be mistaken, I'd know if that house was available."
//if= ERROR,2/txt "$G, Lord British allows only one house per person."
//if= ERROR,3/txt "$G, perhaps you should spend more time exploring Britannia before deciding where to live."
x2=CON_gv(npcbin[x].l2); //housenumber
//already owns house?
for (x3=1;x3<=255;x3++){
if (houseowner(tplayer,x3)){CONerr=2; goto buyhouse_failed;}
}
if (housesav[x2].flags&1){CONerr=1; goto buyhouse_failed;} //already owned?
if (tnpc3->lev<=2){CONerr=3; goto buyhouse_failed;} //inexperienced?
//set house username & charactername 32-byte strings
txtNEWLEN(t3,-32);
for (x3=0;x3<32;x3++){
t3->d2[x3]=0; if (tplayer->name->l>x3) t3->d2[x3]=tplayer->name->d2[x3];
}
txtNEWLEN(t4,-32);
for (x3=0;x3<32;x3++){
t4->d2[x3]=0; if (tnpc3->name->l>x3) t4->d2[x3]=tnpc3->name->d2[x3];
}
//set house.sav buffer
housesav[x2].flags|=1;
housesav[x2].gold=housecost[x2]*3; //3 days
for (x3=0;x3<32;x3++){
housesav[x2].username[x3]=t3->d2[x3];
housesav[x2].charactername[x3]=t4->d2[x3];
}
housesav_update(); //save house.sav buffer to file
//give key (256+housenumber)
myobj3=OBJnew(); myobj3->type=64; myobj3->info=256; myobj3->more2=256+x2;
myobj4=tnpc3->items; myobj5=(object*)myobj4->more;
if (myobj5){
myobj3->next=myobj5;
myobj5->prev=myobj3;
myobj3->prev=myobj4;
myobj4->more=myobj3;
}else{
myobj3->next=NULL;
myobj3->prev=myobj4;
myobj4->more=myobj3;
}
tnpc3->upflags|=32; //inv
tplayer->GNPCflags[28]=x2; //set housenumber
}//party[0]
buyhouse_failed:
x++; goto nextinstruction;
}
if (npcbin[x].l1==30){//economysetup!
x2=CON_gv(npcbin[x].l2);//index
x3=CON_gv(npcbin[x].l3);//initial amount
x4=CON_gv(npcbin[x].l4);//change per Britannian day (+10000 means negative)
if (economy_setup[CONnpc][x2]==FALSE){
economy_setup[CONnpc][x2]=TRUE;
economy_value[CONnpc][x2]=x3;
economy_limit[CONnpc][x2]=x3*2;//DEFAULT LIMIT IS DOUBLE INIT. VALUE
economy_change[CONnpc][x2]=x4;
//adjust value based on hours of already elapsed gameplay
d=ett/3600.0f;//d=days in Brit.(realtime hours)
x3=rnd*100.0f;
d2=((float)x3)/100.0f*3.0f+1.0f;//1-4 (average of 2.5)
d/=d2;//account for exponential factor
x3=d;
x3*=economy_change[CONnpc][x2];
economy_value[CONnpc][x2]+=x3;
if (economy_value[CONnpc][x2]<0) economy_value[CONnpc][x2]=0;
if (economy_value[CONnpc][x2]>economy_limit[CONnpc][x2]) economy_value[CONnpc][x2]=economy_limit[CONnpc][x2];
}
x++; goto nextinstruction;
}
if (npcbin[x].l1==31){//economygetvalue!
x2=CON_gv(npcbin[x].l2);//index
CONreg[0]=economy_value[CONnpc][x2];
x++; goto nextinstruction;
}
if (npcbin[x].l1==32){//economysetvalue!
x2=CON_gv(npcbin[x].l2);//index
x3=CON_gv(npcbin[x].l3);//new value
economy_value[CONnpc][x2]=x3;
if (economy_value[CONnpc][x2]<0) economy_value[CONnpc][x2]=0;
if (economy_value[CONnpc][x2]>economy_limit[CONnpc][x2]) economy_value[CONnpc][x2]=economy_limit[CONnpc][x2];
x++; goto nextinstruction;
}
// Typo? economysetlimit should be instruction #33 per NPC2BIN4.BAS, Xenkan 2010-12-04
//if (npcbin[x].l1==32){//economysetlimit!
if (npcbin[x].l1==33){//economysetlimit!
x2=CON_gv(npcbin[x].l2);//index
x3=CON_gv(npcbin[x].l3);//new limit
economy_limit[CONnpc][x2]=x3;
x++; goto nextinstruction;
}
#pragma region
if (npcbin[x].l1 == 34) // bulkreset
{
memset(tplayer->bulktypes, 0, sizeof(tplayer->bulktypes));
memset(tplayer->bulkqty, 0, sizeof(tplayer->bulkqty));
tplayer->bulkprice = 0;
x++; goto nextinstruction;
}
if (npcbin[x].l1 == 35) // bulktype type,price
{
uint2 type, price, qty;
type = npcbin[x].l2;
price = npcbin[x].l3;
qty = 0;
// search party inventories for item type
object** Inv; uint4 InvCount;
tplayer->GetPartyInventory(&Inv, &InvCount);
for (int i = 0; i < InvCount; i++)
{
if (Inv[i]->type != type ||
Inv[i]->IsStealing() ||
Inv[i]->IsNotForSale())
continue;
if (Inv[i]->IsStackable())
qty += Inv[i]->GetQuantity();
else
qty++;
}
if (qty == 0)
{ x++; goto nextinstruction; }
// find next available sell slot
int slot;
for (slot = 0; tplayer->bulktypes[slot] != 0; slot++);
// add this item type to sell list and price
tplayer->bulktypes[slot] = type;
tplayer->bulkqty[slot] = qty;
tplayer->bulkprice += qty * price;
x++; goto nextinstruction;
}
if (npcbin[x].l1 == 36) // bulksell
{
// verify player still has all items included in quote
object** Inv; uint4 InvCount;
uint2 type, qty;
int i, j;
tplayer->GetPartyInventory(&Inv, &InvCount);
for (i = 0; tplayer->bulkqty[i]; i++)
{
type = tplayer->bulktypes[i];
qty = 0;
for (j = 0; j < InvCount; j++)
{
if (Inv[j]->type != type ||
Inv[j]->IsStealing() ||
Inv[j]->IsNotForSale())
continue;
if (Inv[j]->IsStackable())
qty += Inv[j]->GetQuantity();
else
qty++;
}
if (qty < tplayer->bulkqty[i])
{
CONerr = 1; // player dropped item
x++; goto nextinstruction;
}
}
// remove items
for (i = 0; tplayer->bulkqty[i]; i++)
{
type = tplayer->bulktypes[i];
qty = tplayer->bulkqty[i];
for (j = 0; j < InvCount && qty; j++)
{
if (Inv[j]->type != type ||
Inv[j]->IsStealing() ||
Inv[j]->IsNotForSale())
continue;
if (Inv[j]->IsStackable())
{
if (Inv[j]->GetQuantity() > qty)
{
Inv[j]->SetQuantity(Inv[j]->GetQuantity() - qty);
qty = 0;
}
else
{
qty -= Inv[j]->GetQuantity();
OBJremove(Inv[j]);
OBJrelease(Inv[j]);
}
}
else // not stackable
{
qty--;
OBJremove(Inv[j]);
OBJrelease(Inv[j]);
}
}
}
// give gold
object* gold;
gold = OBJnew();
gold->type = OBJ_GOLD_COIN;
gold->SetQuantity(tplayer->bulkprice);
additemroot((npc*)tplayer->party[0]->more, gold);
// update party's inventory
npc* n;
for (int p = 0; p < 8 && tplayer->party[p]; p++)
{
n = (npc*)tplayer->party[p]->more;
n->upflags |= 32; // update inventory
}
x++; goto nextinstruction;
}
#pragma endregion Bulk sell patch, Xenkan 2010-12-04
//more instructions here
} //myobj!=NULL
talk_skipnullobject:;
txtset(t2,t);
//txtset(t,"NPCmessage ["); txtadd(t,t2); txtadd(t,"] ("); txtnumint(t2,ett); txtadd(t,t2); txtadd(t,")"); txtfileout(t,log2);
goto doneclmess;
} //7
//theory is after receiving a message from host's client we can't reply in the same turn
//txtset(t2,"?"); t2->d2[0]=10; //type 10: U6OID info
//NET_send(NETplayer,NETplayer,t2);
if (t->d2[0]==9){ //type 9: request U6OID info
txtright(t,t->l-1);
tu6oid=t->dl[0];
//whose id is that anyway!!
for (x=0;x<=playerlist_last;x++){
if (playerlist[x]){ //current
if (playerlist[x]->id==tu6oid){
txtset(t2,"?"); t2->d2[0]=10; //type 10: U6OID info
txtadd(t2,t); //U6OID
tnpc=(npc*)playerlist[x]->party[0]->more;
txtset(t3,"?"); t3->d2[0]=tnpc->name->l; txtadd(t2,t3); //->l
txtadd(t2,tnpc->name);
//colour
txtaddchar(t2,playerlist[x]->GNPCflags[245]&255);
txtaddchar(t2,(playerlist[x]->GNPCflags[245]>>8)&255);
txtaddchar(t2,(playerlist[x]->GNPCflags[245]>>16)&255);
NET_send(NETplayer,playerlist[tpl]->net,t2);
goto doneclmess;
}//id
}//current
}//x
goto doneclmess;
} //9
if (t->d2[0]==13){ //->quan
txtright(t,2);
playerlist[tpl]->quan=t->ds[0];
goto doneclmess;
}//13
if (t->d2[0]==15){ //keyboard targeting request
//scan screen from center to outer edges
//as each enemy is found check if they are on our list of 10
//if ktar_wait==0 slot is empty and ready to be filled
//remember to remove any old virtual links before assigning a new one
if (playerlist[tpl]->ktar_display<1.0f){
if (myobj=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
for (i=1;i<=767;i++){
x=myobj->x+ktar_x[i]; y=myobj->y+ktar_y[i];
myobj2=OBJfindlast(x,y); if (myobj2==NULL) myobj2=OBJfindlastall(x,y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
for (i2=0;i2<=9;i2++){
if (playerlist[tpl]->ktar_wait[i2]){
if ((object*)playerlist[tpl]->ktar[i2]->more==myobj2) goto ktar_gottarget;
}}
//add target if room exists
for (i2=0;i2<=9;i2++){ if (!playerlist[tpl]->ktar_wait[i2]){
VLNKremove(playerlist[tpl]->ktar[i2]); VLNKsremove(playerlist[tpl]->ktar[i2]);
playerlist[tpl]->ktar[i2]->more=myobj2;
VLNKnew(playerlist[tpl]->ktar[i2],myobj2,(unsigned long)&playerlist[tpl]->ktar[i2]->more);
playerlist[tpl]->ktar_wait[i2]=64;
goto ktar_gottarget;
}}
}}
ktar_gottarget:;
}//i
}//->party[
}//1.0f
playerlist[tpl]->ktar_display=2.0f;
goto doneclmess;
}//15
if (t->d2[0]==16){ //keyboard target
x=t->d2[1];
if (playerlist[tpl]->ktar_wait[x]){
if (playerlist[tpl]->ktar[x]->more){
//set as target
if (playerlist[tpl]->craft){
if ((playerlist[tpl]->party[0]->type&1023)==412){ //ship
goto kshipattack;
}
}
if (playerlist[tpl]->craft==NULL){
kshipattack:
myobj=(object*)playerlist[tpl]->ktar[x]->more;
crt=(creature*)myobj->more; if (crt->flags&2) goto doneclmess;
for (x2=0;x2<=7;x2++){
if (playerlist[tpl]->party[x2]){
myobj2=playerlist[tpl]->party[x2];
tnpc=(npc*)myobj2->more;
tnpc->order=3;
tnpc->target=myobj;
VLNKsremove(myobj2); //remove prev vlnk
VLNKnew(myobj2,myobj,(unsigned long)&tnpc->target); //add vlnk
if (playerlist[tpl]->craft) goto kshipattack2; //exit loop after processing party[0]
}
}
}
kshipattack2:;
}
}
goto doneclmess;
}//16
if (t->d2[0]==17){ //break off combat
for (x2=0;x2<=7;x2++){
if (playerlist[tpl]->party[x2]){
VLNKsremove(playerlist[tpl]->party[x2]);
tnpc2=(npc*)playerlist[tpl]->party[x2]->more;
tnpc2->target=NULL;
tnpc2->order=3; if (x2==playerlist[tpl]->selected_partymember) tnpc2->order=0;
}//->party
}//x2
goto doneclmess;
}//17
if (t->d2[0]==19){ //typing...
playerlist[tpl]->typing=1;
goto doneclmess;
}//19
if (t->d2[0]==20){ //typing... CANCEL
playerlist[tpl]->typing=0;
goto doneclmess;
}//20
//send pathfinding message
if (t->d2[0]==21){//player pathfind
if (myobj=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
tnpc=(npc*)myobj->more;
txtright(t,t->l-1);
x2=t->ds[0]; y2=t->ds[1];
WPF_OBJECT=myobj; wpf_pathfind(tnpc->path,myobj->x,myobj->y,x2,y2,16,0,0);
if (WPF_RETURN==WPF_PATHFOUND){
if (WPF_PATHLENGTH){
tnpc->path_max=WPF_PATHLENGTH; tnpc->pathn=WPF_PATHLENGTH;
playerlist[tpl]->pathfind=1; //use pathfinding formula!
goto doneclmess;
}
playerlist[tpl]->pathfind=0; tnpc->path_max=0; tnpc->pathn=0;
}
}//party
goto doneclmess;
}//21
if (t->d2[0]==25){ //play MIDI note(s)
//broadcast instrument and notes to all in-range players instantly
txtright(t,t->l-1);
txtset(t2,"??"); t2->d2[0]=27; t2->d2[1]=playerlist[tpl]->instrument; txtadd(t2,t);
if (myobj=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
for (x=0;x<=playerlist_last;x++){
if (playerlist[x]){ //current
if (playerlist[x]->net!=INVALID_NET){
if (myobj2=playerlist[x]->party[playerlist[x]->selected_partymember]){
//proximity check
if (abs(myobj2->x-myobj->x)<=16){ if (abs(myobj2->y-myobj->y)<=12){
NET_send(NETplayer,playerlist[x]->net,t2);
}}
}//myobj2
}}}//x valid
}//myobj
goto doneclmess;
}//25
if (t->d2[0]==26){ //stop MIDI note(s)
//broadcast instrument and notes to all in-range players instantly
txtright(t,t->l-1);
txtset(t2,"??"); t2->d2[0]=28; t2->d2[1]=playerlist[tpl]->instrument; txtadd(t2,t);
if (myobj=playerlist[tpl]->party[playerlist[tpl]->selected_partymember]){
for (x=0;x<=playerlist_last;x++){
if (playerlist[x]){ //current
if (playerlist[x]->net!=INVALID_NET){
if (myobj2=playerlist[x]->party[playerlist[x]->selected_partymember]){
//proximity check
if (abs(myobj2->x-myobj->x)<=16){ if (abs(myobj2->y-myobj->y)<=12){
NET_send(NETplayer,playerlist[x]->net,t2);
}}
}//myobj2
}}}//x valid
}//myobj
goto doneclmess;
}//26
/*
txtset(t,"?"); t->d2[0]=25; //play MIDI keys
txtset(t2,"?");
//multiple keys can point to a single sound
for (i=0;i<=255;i++){
if (keyhit(i)){
if (t->l<9){
t2->d2[0]=midikeyboard2[i];
txtadd(t,t2);
midikeyboard2_keyon[i]=1;
}
}//keyhit
}//i
if (t->l>1){
NET_send(NETplayer,NULL,t);
}
txtset(t,"?"); t->d2[0]=26; //stop MIDI keys
txtset(t2,"?");
for (i=0;i<=255;i++){
if (keyon[i]==NULL){
if (midikeyboard2_keyon[i]){
t2->d2[0]=midikeyboard2[i]; txtadd(t,t2);
midikeyboard2_keyon[i]=0;
}}}
if (t->l>1){
NET_send(NETplayer,NULL,t);
}
*/
//if (playerlist[tpl]->net==1){
//goto U6Ohostlink1;
//U6Ohostlink1return:;
//}
doneclmess:
goto nextclientmessage;
} //read client message
} //host
if (NEThost){
//host schedule info
f=16.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
u6orevive++; if (u6orevive==200) u6orevive=0;
seek(u6orevive_fh,0); put(u6orevive_fh,&u6orevive,1);
}
u6opi=40;
f=64.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
inbritanniacheck();
}
u6opi=41;
//host log report
f=60.0f; if (int((ett/f))!=int((ett/f)-(et/f))){ //every minute
txtset(t,"[In_Britania:"); txtadd(t,inbritannia); txtadd(t,"]");
txtnumint(t2,framerate);
txtadd(t,"[Framerate:"); txtadd(t,t2); txtadd(t,"]");
txtnumint(t2,vlnkb_last);
txtadd(t,"[vlnkb_last(MAX=65536):"); txtadd(t,t2); txtadd(t,"]");
txtnumint(t2,objb_last);
txtadd(t,"[objb_last(MAX=524228):"); txtadd(t,t2); txtadd(t,"]");
LOGadd(t);
}
//if (ett>=86400){
/*
f=4.0f; if (int((ett/f))!=int((ett/f)-(et/f))){ //8min delay till removal
txtset(t,"!");
txtadd(t," vlnkb_last="); txtnumint(t2,vlnkb_last); txtadd(t,t2);
txtadd(t," vlnkb_free_last="); txtnumint(t2,vlnkb_free_last); txtadd(t,t2);
txtadd(t," framerate="); txtnumint(t2,framerate); txtadd(t,t2);
txtadd(t," ("); txtnumint(t2,ett); txtadd(t,t2); txtadd(t,")"); txtfileout(t,log2);
}
*/
/*
long objsave_last=-1;
unsigned short objsave_x[65536];
unsigned short objsave_y[65536];
object *objsave_obj[65536]; //pointer to first saved object
float objsave_wait[65536];
*/
u6opi=42;
//add saved objects
for (i=0;i<=objsave_last;i++){
if (objsave_obj[i]){
objsave_wait[i]-=et; if (objsave_wait[i]<=0){
//1st pass: destroy ALL temp objects (except deeds and selected critical items)
myobj3=NULL; //add saved objects after this object
if (myobj=od[objsave_y[i]][objsave_x[i]]){
addsaveclear:
myobj2=(object*)myobj->next;
if ((myobj->type&1023)==414) goto addsaveclearskip; //skiff
if ((myobj->type&1023)==149) goto addsaveclearskip; //deed
//add more here
if (myobj->info&112){//temp object
OBJremove(myobj);
}else{
//object wasn't removed!
if (objfloatflags[(myobj->type>>10)+sprlnk[myobj->type&1023]]==NULL){
if (obji[sprlnk[myobj->type&1023]].v4==NULL){ //not crt/npc
myobj3=myobj; //set as base item if NOT floating
}//not crt/npc
}//float==NULL
}//info&112
addsaveclearskip:
if (myobj2) {myobj=myobj2; goto addsaveclear;}
}
u6opi=421;
if (myobj3){ //temp set to end of stack
myobj4=(object*)myobj3->next; myobj3->next=NULL;
}else{
myobj4=od[objsave_y[i]][objsave_x[i]]; od[objsave_y[i]][objsave_x[i]]=NULL;
}
//add objects
myobj=objsave_obj[i];
addsaveobj:
myobj2=(object*)myobj->next;
myobj->next=NULL; myobj->prev=NULL;
OBJadd(objsave_x[i],objsave_y[i],myobj);
//multi-tile container FIX
x=0; y=0;
if (myobj->type==(176+1024)) x=-1;
if (myobj->type==(176+3*1024)) y=-1;
if (myobj->type==(168+1024)) x=-1;
if (myobj->type==(168+3*1024)) y=-1;
if (myobj->type==(341+3*1024)) {y=-1; x=-1;}
if (myobj->type==(340+3*1024)) {y=-1; x=-1;}
if (x||y){
addsave_mtcfix2:
if (myobj5=od[myobj->y+y][myobj->x+x]){
addsave_mtcfix:
if ((myobj5->type&1023)==(myobj->type&1023)){
if (myobj5->info&8){
myobj5->more=(object*)myobj;
}//info&8
}//type&1023
if (myobj5=(object*)myobj5->next) goto addsave_mtcfix;
}//myobj5
if ((x==-1)&&(y==-1)&&(myobj->type==(341+3*1024))) {y=-1; x=0; goto addsave_mtcfix2;}
if ((x==0)&&(y==-1)&&(myobj->type==(341+3*1024))) {y=0; x=-1; goto addsave_mtcfix2;}
if ((x==-1)&&(y==-1)&&(myobj->type==(340+3*1024))) {y=-1; x=0; goto addsave_mtcfix2;}
if ((x==0)&&(y==-1)&&(myobj->type==(340+3*1024))) {y=0; x=-1; goto addsave_mtcfix2;}
}//x||y
if (myobj2) {myobj=myobj2; goto addsaveobj;}
if (myobj4) {myobj->next=myobj4; myobj4->prev=myobj;}
OBJcheckflags(objsave_x[i],objsave_y[i]);
objsave_obj[i]=NULL; //invalidate
}//wait<=0
}//objsave_obj
}//i
u6opi=43;
//remove temporary objects
f=64.0f; if (int((ett/f))!=int((ett/f)-(et/f))){ //8min delay till removal
//f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){ //8min delay till removal
i=2048*1024; while (i--){
if (myobj=od[objr_y][objr_x]){
tempcheck:
myobj2=(object*)myobj->next;
//skip SPECIAL temp objects
for (i2=0;i2<=nresu;i2++){ if (resu[i2]){ //if in resurrect list DO NOT remove!
if (resu_body[i2]==myobj) goto skiptempobj;
}}
if ((myobj->type&1023)==412) goto skiptempobj; //ship
if ((myobj->type&1023)==414) goto skiptempobj; //skiff
if ((myobj->type&1023)==149) goto skiptempobj; //deed
if (myobj->type==OBJ_HORSE_PAPERS) goto skiptempobj; //horse papers
if (obji[sprlnk[myobj->type&1023]].flags&1024){ //container
if ((myobj->type&1023)!=OBJ_DEAD_CYCLOPS){
if ((myobj->type&1023)!=OBJ_DEAD_GARGOYLE){
if ((myobj->type&1023)!=OBJ_DEAD_REAPER){
if ((myobj->type&1023)!=OBJ_HORSE_CARCASS){//carcass
if (obji[sprlnk[myobj->type&1023]].weight==NULL) goto skiptempobj; //NULL weight container
}
}
}
}
}
//house storage exception
for (i3=1;i3<=255;i3++){
for (i4=0;i4<housestoragenext[i3];i4++){
if (myobj->x==housestoragex[i3][i4]){ if (myobj->y==housestoragey[i3][i4]){
goto skiptempobj;
}}//x,y
}//i4
}//i3
//-1/remove object
i2=(myobj->info>>4)&7;
if (i2){
i2--; myobj->info&=(32767-112); myobj->info+=(i2<<4);
if (i2==0){
if (myobj->info&2) { //NPC
tnpc=(npc*)myobj->more;
free(tnpc);
}
OBJremove(myobj);
OBJrelease(myobj);
}
}
skiptempobj:
if (myobj2) {myobj=myobj2; goto tempcheck;}
}
objr_x++;
if (objr_x>2047){objr_x=0; objr_y++;}
if (objr_y>1023) objr_y=0;
}
}
u6opi=44;
//respawn info
//respawn_last++;
//respawn[respawn_last]=myobj2;
//respawn_delay[respawn_last]=16;
//fruit tart, dog lead?, dog home?
/*
void *respawn[16384];
unsigned short respawn_delay[16384]; //number of seconds till creature will respawn
//*note: creature will not respawn if player is too near (eg. 8 squares or less)
long respawn_last=-1;
*/
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
for (i=0;i<=respawn_last;i++){
if (respawn[i]){
respawn_delay[i]--;
if (respawn_delay[i]==0){
crt=(creature*)respawn[i]->more;
u6opi=441;
//player nearby?
x=crt->respawn_x; y=crt->respawn_y; //GPF
z=12; if ((x>=1024)&&(!((y>=256)&&(x<1280)&&(y<512)))) z=8; //not on overland map or garglands
for (i2=0;i2<=playerlist_last;i2++){
if (playerlist[i2]){ //current player
if (playerlist[i2]->net!=INVALID_NET){ //net connection available
if (playerlist[i2]->party[0]){
//if abs(playerlist[i2]->party[0]->x-crt->respawn_x)<=
x2=playerlist[i2]->party[0]->x; y2=playerlist[i2]->party[0]->y;
x2=abs(x-x2); y2=abs(y-y2);
if ((x2<=z)||(y2<=z)){
respawn_delay[i]=512; //~8mins
goto respawn_failed;
}//x2<=z,y2<=z
}
}
}//net
}//i2
u6opi=442;
if (crt->flags&32){ //revert charmed creature!
crt->al=1; crt->charm=0;
}
//revert passive->aggresive
if ((respawn[i]->type&1023)==382){ //guard
if (crt->respawn_x<1024) crt->al=4; //not underground
}
if ((respawn[i]->type&1023)==373) crt->al=0; //wisp
if ((respawn[i]->type&1023)==430) crt->al=0; //horse
if ((respawn[i]->type&1023)==428) crt->al=0; //cow
if ((respawn[i]->type&1023)==356) crt->al=0; //bird
if ((respawn[i]->type&1023)==348) crt->al=0; //sheep
if ((respawn[i]->type&1023)==350) crt->al=0; //deer
if ((respawn[i]->type&1023)==388){ //cat
if ((crt->respawn_x>=400)&&(crt->respawn_y>=576)&&(crt->respawn_x<=415)&&(crt->respawn_y<=591)) crt->al=0; //Dr Cat's cats
}
if ((respawn[i]->type&1023)==352){ //ghost
if ((crt->respawn_x==139)&&(crt->respawn_y==196)) crt->al=0; //abby ghosts
}
crt->hp=crt->respawn_hp;
crt->mp=rnd*9;
crt->flags=0;
myobj2=respawn[i];
//2006 monster drops
static object *invbag,*invobj,*xpgoldobj;
invbag=crt->items;
if (crt->al==1){//aggressive
addu6monsterdropitems(myobj2);
//integrate XP based gold
x9=rnd*8; if (x9==0){
x9=obji[sprlnk[myobj2->type&1023]].v5; x9=rnd*(x9+1); if (x9){
if (xpgoldobj=(object*)invbag->more){
respawn_goldscan:
if (xpgoldobj->type==OBJ_GOLD_COIN){
xpgoldobj->more2+=x9;
goto respawn_goldadded;
}
xpgoldobj=(object*)xpgoldobj->next; if (xpgoldobj) goto respawn_goldscan;
}
invobj=OBJnew(); invobj->type=88; invobj->more2=x9;
invobj->info|=112; invobj->next=invbag->more; invobj->prev=invbag; invbag->more=invobj; if (invobj->next) ((object*)invobj->next)->prev=invobj;
}
}
respawn_goldadded:
goto respawn_u6inventoryadded;
}//al==1
if (((myobj2->type&1023)==428)||((myobj2->type&1023)==348)||((myobj2->type&1023)==350)){//cow/sheep/deer
x9=rnd*2; if (x9){
invobj=OBJnew(); invobj->type=129; invobj->more2=1;//add meat
invobj->info|=112; invobj->next=invbag->more; invobj->prev=invbag; invbag->more=invobj; if (invobj->next) ((object*)invobj->next)->prev=invobj;
}//x9
}//cow/sheep/deer
respawn_u6inventoryadded:
/*
//add gold/items to inventory
//add gold
if (crt->al==1){
x9=obji[sprlnk[myobj2->type&1023]].v5>>2;
//x9++; //plus 1 for rookie luck
x9=rnd*(x9+1);
if (x9){
myobj8=OBJnew(); myobj8->type=88; myobj8->more2=x9;
//items<-gold
myobj6=crt->items; myobj7=(object*)myobj6->more;
if (myobj7!=NULL){
myobj8->next=myobj7; myobj7->prev=myobj8; myobj8->prev=myobj6; myobj6->more=myobj8;
}else{
myobj8->next=NULL; myobj8->prev=myobj6; myobj6->more=myobj8;
}
}//x9
}//al==1
//add meat
if (((myobj2->type&1023)==428)||((myobj2->type&1023)==348)||((myobj2->type&1023)==350)){//cow&sheep&deer
x9=rnd*2; if (x9){
myobj8=OBJnew(); myobj8->type=129; myobj8->more2=1; //<-meat
myobj6=crt->items; myobj7=(object*)myobj6->more;
if (myobj7!=NULL){
myobj8->next=myobj7; myobj7->prev=myobj8; myobj8->prev=myobj6; myobj6->more=myobj8;
}else{
myobj8->next=NULL; myobj8->prev=myobj6; myobj6->more=myobj8;
}
}//x9
}//cow
*/
if ((myobj2->type&1023)==375) myobj2->info|=(3<<9); //slime divide!
OBJmove_allow=TRUE;
OBJmove2(respawn[i],crt->respawn_x,crt->respawn_y);
//silver serpent "recoil"
if ((respawn[i]->type&1023)==413){
OBJmove2(respawn[i],crt->respawn_x,crt->respawn_y+1);
OBJmove2(respawn[i],crt->respawn_x+1,crt->respawn_y+1);
OBJmove2(respawn[i],crt->respawn_x+1,crt->respawn_y);
OBJmove2(respawn[i],crt->respawn_x,crt->respawn_y);
OBJmove2(respawn[i],crt->respawn_x,crt->respawn_y+1);
OBJmove2(respawn[i],crt->respawn_x+1,crt->respawn_y+1);
OBJmove2(respawn[i],crt->respawn_x+1,crt->respawn_y);
OBJmove2(respawn[i],crt->respawn_x,crt->respawn_y);
}
OBJmove_allow=FALSE;
crt->target=NULL;
respawn[i]=NULL;
respawn_failed:;
}//delay
}//respawn[i]
}//i
}//f
u6opi=5;
//update objects/creatures/npc
if (ouln!=-1){
for (i=0;i<=ouln;i++){
if (myobj=oul[i]){
//skip objects in void!
if ((myobj->y>=1000)&&(myobj->x>=2016)) goto skip_ouli;
//if ((myobj->y>=256)&&(myobj->x>=1280)) goto skip_ouli; //2005: free map area
i2=myobj->type&1023;
//i,i2 reserved, all other free
if (myobj->type==(223+1024)){ //powder keg
f=0.25f; if (int((ett/f))!=int((ett/f)-(et/f))){
x=(myobj->info>>9)&15;
x--;
myobj->info=(myobj->info&(0xFFFF-7680))+(x<<9);
if (!x){
static object *powderkeg;
powderkeg=myobj;
myobj=NULL; tnpc=NULL;
for (x2=0;x2<=playerlist_last;x2++){
if (playerlist[x2]){
tplayer2=playerlist[x2];
if (tplayer2->id==powderkeg->more2){
if (tplayer2->party[0]){
myobj=tplayer2->party[0];
tnpc=(npc*)myobj->more;
}
goto powderkeg_gotsource;
}
}
}
powderkeg_gotsource:
static long spellx,spelly;
//copied from "explosion spell"
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (OBJcheckbolt(powderkeg->x,powderkeg->y,powderkeg->x+spellx,powderkeg->y+spelly)) goto explosionblocked2;
myobj2=OBJfindlast(powderkeg->x+spellx,powderkeg->y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(powderkeg->x+spellx,powderkeg->y+spelly);
if (myobj2){
if ((myobj2->info&8)==0){ //no redirector
x2=myobj2->type&1023; x3=myobj2->type>>10;
if ((x2>=297)&&(x2<=300)){ //door
if ((x3>=4)&&(x3<12)){ //closed but not magically locked
x4=4;
if (x3>=8){ //door is locked and needs unlocking
myobj3=OBJfindlastall(myobj2->x,myobj2->y);
if (myobj3->info&8) myobj3=(object*)myobj3->more; //<-redirect
if (myobj3->more2) goto powderkeg_needskey;
x4=8;
}
myobj2->type=(myobj2->type&1023)+(((myobj2->type>>10)-x4)<<10); OBJcheckflags(myobj2->x,myobj2->y);
myobj2=(object*)myobj2->more;
myobj2->type=(myobj2->type&1023)+(((myobj2->type>>10)-x4)<<10); OBJcheckflags(myobj2->x,myobj2->y);
if (tnpc){ if (tnpc->player){
txtset(t,"?The door was blown open!"); t->d2[0]=8; NET_send(NETplayer,tnpc->player->net,t);
}}
goto powderkeg_dooropened;
}
}
powderkeg_needskey:
if ((myobj2->type&1023)==98){ //chest
if ((myobj2->type>>10)<=2){ //not magically locked
//destroy chest and extract objects
x3=myobj2->x; y3=myobj2->y;
OBJsave(x3,y3);
VLNKremove(myobj2);
OBJremove(myobj2);
extractobj6:
myobj3=(object*)myobj2->more;
if (myobj3) {OBJremove(myobj3); myobj3->info|=112; OBJadd(x3,y3,myobj3); goto extractobj6;}
}
}//98
if ((myobj2->type&1023)==223){ //powder keg
if (myobj2!=powderkeg){
if ((myobj2->more2==0)||(myobj2->more2==powderkeg->more2)){
OBJsave(myobj2->x,myobj2->y);
myobj2->info=(myobj2->info&(0xFFFF-7680))+(1<<9);
myobj2->type=223+1*1024;
myobj2->more2=powderkeg->more2;
}
}
}
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
x2=rnd*96;
if (x2==0) goto explosion_spelldone2;
//fire resistant???
i3=myobj2->type&1023;
if (i3==411) {x2=0; goto IFimmuneflame3;} //dragon
if (i3==369) {x2=0; goto IFimmuneflame3;} //drake
if (i3==352) {x2=0; goto IFimmuneflame3;} //ghost
if (i3==374) {x2=0; goto IFimmuneflame3;} //hydra
if (i3==369) {x2=0; goto IFimmuneflame3;} //drake
if (i3==368) {x2=0; goto IFimmuneflame3;} //skeleton
if (i3==373) {x2=0; goto IFimmuneflame3;} //wisp
if (i3==367) {x2=0; goto IFimmuneflame3;} //daemon
//double damage?
if (i3==364) x2*=2; //acid slug
if (i3==357) x2*=2; //corpser
if (i3==347) x2*=2; //reaper
if (i3==360) x2*=2; //rot worms
if (i3==375) x2*=2; //slime
if (i3==365) x2*=2; //tangle vine
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
CASTSPELL_SPELLTYPE=65535;
spellattcrt=TRUE; goto spellattcrt0;
IFimmuneflame3:;
}//crt
if (myobj2->info&2){ //npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
if (tnpc2->player->id==powderkeg->more2){
x2=rnd*48;
x3=rnd*(tnpc2->arm+1);
x2-=x3; if (x2<0) x2=0;
if (x2){
tnpc2->hp-=x2;
tnpc2->upflags|=2; //hp
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
}//x2
}//id
}//player
}//npc
}//no redirector
}//myobj2
explosion_spelldone2:
powderkeg_dooropened:
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(powderkeg->x+spellx,powderkeg->y+spelly);
sf[i9].type=8; //wand
sf[i9].x=powderkeg->x;
sf[i9].y=powderkeg->y;
sf[i9].x2=powderkeg->x+spellx;
sf[i9].y2=powderkeg->y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
explosionblocked2:;
}//!=4
}}//spell x,y
OBJremove(powderkeg);
}//!x
}//f
goto skip_ouli;
}
if (myobj->info&4){ //<-crt
static unsigned char target_struct; target_struct=2;
x=myobj->x; y=myobj->y;
if (crt=(creature*)myobj->more){
if (crt->hp!=NULL){
if (crt->flags&2){ //invisible!
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
x2=rnd*64; if (!x2) crt->flags-=2;
x2=rnd*16; if (!x2) VLNKremove(myobj);
}//1.0
}//2
if (crt->flags&32){ //charmed!
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (crt->charm>0){
crt->charm--;
}else{crt->flags-=32; crt->al=1;}
}//1.0
}//32
if (crt->flags&1){ //poisoned?
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
x2=rnd*2; if (x2==0){
if (crt->hp) crt->hp--;
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=1;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
}}}
if (myobj2=(object*)myobj->prev){
if (myobj2->type==OBJ_POISON_FIELD){ //poison field
crt->flags|=1; //poison creature
}
if (myobj2->type==OBJ_FIRE_FIELD){ //fire field -8hp/sec
i3=myobj->type&1023;
x2=2;
if (i3==411) x2=0; //dragon
if (i3==369) x2=0; //drake
if (i3==352) x2=0; //ghost
if (i3==374) x2=0; //hydra
if (i3==369) x2=0; //drake
if (i3==368) x2=0; //skeleton
if (i3==373) x2=0; //wisp
if (i3==367) x2=0; //daemon
//double damage?
if (i3==364) x2*=2; //acid slug
if (i3==357) x2*=2; //corpser
if (i3==347) x2*=2; //reaper
if (i3==360) x2*=2; //rot worms
if (i3==375) x2*=2; //slime
if (i3==365) x2*=2; //tangle vine
if (x2){
f=0.5f; if (int((ett/f))!=int((ett/f)-(et/f))){
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=x2; //attack
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
crt->hp--;
}//f
}//x2
}//fire field
if (myobj2->type==OBJ_SLEEP_FIELD){ //sleep field
x2=4+rnd*16;
//immune to sleep?
i3=myobj->type&1023;
if (i3==364) x2=0; //acid slug
if (i3==427) x2=0; //ant
if (i3==357) x2=0; //corpser
if (i3==367) x2=0; //daemon
if (i3==362) x2=0; //winged garg
if (i3==363) x2=0; //garg
if (i3==355) x2=0; //gazer
if (i3==352) x2=0; //ghost
if (i3==374) x2=0; //hydra
if (i3==343) x2=0; //insects
if (i3==347) x2=0; //reaper
if (i3==360) x2=0; //rotworms
if (i3==426) x2=0; //scorpion
if (i3==368) x2=0; //skeleton
if (i3==375) x2=0; //slime
if (i3==345) x2=0; //squid
if (i3==365) x2=0; //tanglevine
if (i3==373) x2=0; //wisp
if ((crt->flags&4)==0){
//NOTE: sleep uses a paralyze effect, but to identify the difference visually (sleeping body) asleep flag is set
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
crt->wait+=x2; crt->flags|=(4+8); //1=poison, 2=invisible, 4=asleep, 8=paralyzed
}//f
}
}//sleep field
if (myobj2->type==OBJ_WEB){ //web paralyze monsters
x2=rnd*3;
if (x2==0) {
x2=4+rnd*8;
//immune to sleep?
i3=myobj->type&1023;
if (i3==OBJ_GIANT_SPIDER) x2=0; //giant spider
if ((crt->flags&8)==0){
//make creature stuck in the web
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
crt->wait+=x2; crt->flags|=8; //1=poison, 2=invisible, 4=asleep, 8=paralyzed
}//f
}
}
}//web
}//prev object
if (crt->respawn_hp==0){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
crt->respawn_x--; if (crt->respawn_x==0) goto summonedcreature_remove;
}
}
if ((myobj->type&1023)==366) crt->hp=32767; //invincible tanglevine tendril!
if ((myobj->type&1023)==430) if (crt->flags&128) crt->hp=32767;//invincible horse
//creature died!
if (crt->hp<=0){
summonedcreature_remove:
myobj2=myobj;
myobj4=(object*)crt->items->more; //will point to first item
dropgoldmore2:
if (myobj4){
myobj5=(object*)myobj4->next;
OBJmove_allow=TRUE;
OBJmove(myobj4,myobj2->x,myobj2->y);
OBJmove_allow=FALSE;
myobj4->info|=112; //set flags as temp OBJ
if (myobj5) {myobj4=myobj5; goto dropgoldmore2;}
}
crtrespawn(myobj2);
goto donemove;
}//hp<=0
static unsigned char crt_casti=0;
f=0.25f; if (int((ett/f))!=int((ett/f)-(et/f))) { //cast
x2=rnd*32;
if (x2==0){
crt->cast=1;
}//x2==0
}//cast
f=8.0f-((float)(obji[sprlnk[myobj->type&1023]].v7&255))/8.0f; //mp+ interval
if (int((ett/f))!=int((ett/f)-(et/f))) { //increase mp
crt->mp++; if (crt->mp>8) crt->mp=8;
if (crt->mp==8) crt->cast=1; //force cast on max mp
}
static object* validate_obj;
validate_obj=NULL;
crt->wait-=et; if (crt->wait<0) crt->wait=0;
if (crt->target){
f=2.0f; if (int((ett/f))!=int((ett/f)-(et/f))) { //reselect target
if ((crt->al==1)||(crt->al==4)){ //not al==3(passive turned aggresive)
x2=rnd*32;
if (x2==0){
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0; goto donemove;
}
}//al
}//reselect target
f=0.5f; if (int((ett/f))!=int((ett/f)-(et/f))){ //validate target (~once every 4 sec)
if ((crt->al==1)||(crt->al==4)){ //not al==3(passive turned aggresive)
x2=rnd*8;
if (x2==0){
validate_obj=crt->target;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0;
}
}
}//validate target
}//crt->target
if (crt->wait==0){
if (crt->flags&8) crt->flags-=8; //unparalyze //1=poison, 2=invisible, 4=asleep, 8=paralyzed
if (crt->flags&4) crt->flags-=4; //awaken //1=poison, 2=invisible, 4=asleep, 8=paralyzed
if (crt->al==0){
x2=rnd*4; x3=x; y3=y;
if (x2==0) x3--;
if (x2==1) x3++;
if (x2==2) y3--;
if (x2==3) y3++;
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
goto crt_walk; //wander
}//al==0
//STEP 1: ENUMERATE TARGETS
/*
struct crtenum_struct{
char x;
char y;
};
crtenum_struct crtenum[1073];
object* crtenum_pathok_castok[1024]; short crtenum_pathok_castok_i;
object* crtenum_pathok[1024]; short crtenum_pathok_i;
object* crtenum_castok[1024]; short crtenum_castok_i;
significant changes:
can't target on diagonals (goes for party npc too)
should CHECK for best target randomly every 8 seconds, keeping current target only if it is the best
MUST ALWAYS SELECT A TARGET FROM THE "BEST" GROUP
BEST ORDER:
1. PATH+MAGIC
2. PATH ONLY
3. MAGIC ONLY
these 3 changes will fix 99% of combat issues
*/
if (!crt->target){
x4=myobj->type&1023; x5=1; //movement type
if (x4==365) x5=-1; //tanglevine
if (x4==347) x5=-1; //reaper
if (x4==345) x5=2; //squid
if (x4==346) x5=2; //sea serpent
if (x4==343) x5=3; //insects
if (x4==344) x5=3; //bat
if (x4==356) x5=3; //bird
if (x4==362) x5=3; //winged gargoyle
if (x4==369) x5=3; //drake
if (x4==372) x5=3; //mongbat
if (x4==373) x5=3; //wisp
if (x4==411) x5=3; //dragon
if (x4==352) x5=4; //GHOST (4=unlimited!)
if (x4==366) x5=5; //tanglevine tendril
//ERROR!!! DO PASSIVE MONSTERS NEED TO ENUMERATE??? NO THEY DO NOT!!
//on surface max distance is 18
//max distance underground is 10
i4=18; if ((x>=1024)&&(!((y>=256)&&(x<1280)&&(y<512)))) i4=10; // fixed so that excludes gargland properly
ZeroMemory(&wpf_sourcedest,sizeof(wpf_sourcedest));
WPF_OBJECT=myobj; if (x5!=-1) wpf_pathfind(NULL,x,y,0,0,i4,x5,8);//find all accessable squares
target_struct=2+4; //target NPC + CRT
if (crt->al==4) target_struct=4; //target CRT
crtenum_pathok_castok_i=-1; crtenum_pathok_i=-1; crtenum_castok_i=-1;
i4=1072; if ((x>=1024)&&(!((y>=256)&&(x<1280)&&(y<512)))) i4=440;
for (x2=0;x2<=i4;x2++){
x3=x+crtenum[x2].x; y3=y+crtenum[x2].y;
if (myobj2=od[y3][x3]){
if ((x3>=0)&&(x3<=2047)&&(y3>=0)&&(y3<=1023)){
crtenum_next:
if (myobj2->info&target_struct){ //gpg top right corner of map dead guys
tnpc2=(npc*)myobj2->more;
i3=1;
if (target_struct==4){ //targeting CRT only, crt is friendly
if (tnpc2->al!=1) i3=0;
}else{ //targeting NPC + CRT, crt is NOT friendly
if (myobj2->info&2){
//target_struct=2;
if (tnpc2->player){
if (((myobj->type&1023)==362)||((myobj->type&1023)==363)){//gargoyle
if (myobj->x>=1024){ if (myobj->y>=256){
if (myobj->x<1280){ if (myobj->y<512){
//amulet of submission check
tplayer2=tnpc2->player;
if (tplayer2->GNPCflags[12]) i3=0; //has amulet of submission or has finished game
//beh lem check! (the tricky one) (if he is dead gargs attack, and this is only natural)
for (x4=1;x4<=7;x4++){
if (tplayer2->party[x4]){
tnpc3=(npc*)tplayer2->party[x4]->more;
if (tnpc3->converse==162) i3=0;
}//tplayer2->party[x4]
}//x4
}}}}//x,y,x,y
}//gargoyle
}else{
i3=0; //crt can't attack passive NPC
}
}else{
//target_struct=4;
if (tnpc2->al!=4) i3=0; //crt can't attack al==1 or passive monsters
}//info&2
}//target_struct==4
if (tnpc2->flags&2) i3=0; //crt can't target invisible CRT/NPC
if (i3){
i3=3;
//check path finding
x4=abs(myobj->x-myobj2->x); y4=abs(myobj->y-myobj2->y);
if ((x4<=1)&&(y4<=1)) goto crtenum_close;
if (x5==-1){i3--; goto crtenum_close;}
i5=1;
if (wpf_sourcedest[myobj2->x-WPF_OFFSETX][myobj2->y-WPF_OFFSETY]&1) i5=0;
if (wpf_sourcedest[myobj2->x-WPF_OFFSETX-1][myobj2->y-WPF_OFFSETY]&1) i5=0;
if (wpf_sourcedest[myobj2->x-WPF_OFFSETX+1][myobj2->y-WPF_OFFSETY]&1) i5=0;
if (wpf_sourcedest[myobj2->x-WPF_OFFSETX][myobj2->y-WPF_OFFSETY-1]&1) i5=0;
if (wpf_sourcedest[myobj2->x-WPF_OFFSETX][myobj2->y-WPF_OFFSETY+1]&1) i5=0;
i3-=i5;
crtenum_close:
//check casting
if ((abs(x-x3)<=8)&&(abs(y-y3)<=8)){ //in spell range!
if (OBJcheckbolt(x,y,x3,y3)) i3-=2; //blocked
}else{
i3-=2;
}
if (i3==3) {crtenum_pathok_castok_i++; crtenum_pathok_castok[crtenum_pathok_castok_i]=myobj2;}
if (i3==2) {crtenum_castok_i++; crtenum_castok[crtenum_castok_i]=myobj2;}
if (i3==1) {crtenum_pathok_i++; crtenum_pathok[crtenum_pathok_i]=myobj2;}
}//i3
}//myobj2->info&target_struct
if (myobj2->next){ myobj2=(object*)myobj2->next; goto crtenum_next;}
}//x&y check
}//myobj2
}//x2
//choose a target based on enumerated info
if ((crtenum_pathok_castok_i==-1)&&(crtenum_pathok_i==-1)&&(crtenum_castok_i==-1)){ //no target!
validate_obj=NULL;
x2=rnd*4; x3=x; y3=y;
if (x2==0) x3--;
if (x2==1) x3++;
if (x2==2) y3--;
if (x2==3) y3++;
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
goto crt_walk; //wander
}
if (crtenum_pathok_castok_i!=-1){
if (validate_obj){
for (x2=0;x2<=crtenum_pathok_castok_i;x2++){
if (crtenum_pathok_castok[x2]==validate_obj){
validate_obj=NULL; myobj2=crtenum_pathok_castok[x2]; goto crtenum_gottarget;
}
}//x2
validate_obj=NULL;
}//validate_obj
x2=0;
crtenum_selecttarget:
myobj2=crtenum_pathok_castok[x2];
y2=rnd*2; if (y2||(crtenum_pathok_castok_i==x2)) goto crtenum_gottarget;
if (crtenum_pathok_castok_i>x2){ x2++; goto crtenum_selecttarget;}
}
if (crtenum_pathok_i!=-1){
if (validate_obj){
for (x2=0;x2<=crtenum_pathok_i;x2++){
if (crtenum_pathok[x2]==validate_obj){
validate_obj=NULL; myobj2=crtenum_pathok[x2]; goto crtenum_gottarget;
}
}//x2
validate_obj=NULL;
}//validate_obj
x2=0;
crtenum_selecttarget2:
myobj2=crtenum_pathok[x2];
y2=rnd*2; if (y2||(crtenum_pathok_i==x2)) goto crtenum_gottarget;
if (crtenum_pathok_i>x2){ x2++; goto crtenum_selecttarget2;}
}
if (crtenum_castok_i!=-1){
if (validate_obj){
for (x2=0;x2<=crtenum_castok_i;x2++){
if (crtenum_castok[x2]==validate_obj){
validate_obj=NULL; myobj2=crtenum_castok[x2]; goto crtenum_gottarget;
}
}//x2
validate_obj=NULL;
}//validate_obj
x2=0;
crtenum_selecttarget3:
myobj2=crtenum_castok[x2];
y2=rnd*2; if (y2||(crtenum_castok_i==x2)) goto crtenum_gottarget;
if (crtenum_castok_i>x2){ x2++; goto crtenum_selecttarget3;}
}
crtenum_gottarget:
VLNKsremove(myobj); //remove any prev vlnk(s) created
crt->target=myobj2; crt->pathn=0;
VLNKnew(myobj,crt->target,(unsigned long)&crt->target); //add new vlnk to target
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
if (myobj2->info&2){ //play battle music!
tnpc=(npc*)myobj2->more;
if (tnpc->player){
if (obji[sprlnk[myobj->type&1023]].v5>=10){
//battle music: melee
txtset(t,"????");
t->d2[0]=30;
t->d2[1]=9; //melee.mid
t->ds[1]=32; //seconds to play midi for
NET_send(NETplayer,tnpc->player->net,t);
}
}
}
goto donemove;
}//->target==NULL
//STEP 2: REVALIDATE TARGET
myobj2=crt->target;
//empty skiff/boat/...?
if ((myobj2->info&(2+4))==0) goto invalidatetarget;
tnpc=(npc*)myobj2->more; crt2=(creature*)tnpc; target_struct=myobj2->info&(2+4);
//invisible?
if (tnpc->flags&2) goto invalidatetarget;
//recheck allegiance
if (target_struct==4){ //targeting CRT
if ((crt->al==1)&&(crt2->al==1)) goto invalidatetarget;
if ((crt->al==4)&&(crt2->al==4)) goto invalidatetarget;
}else{ //targeting NPC
if (!tnpc->player) goto invalidatetarget;
if (crt->al==4) goto invalidatetarget;
}
goto revalidatetargetok;
invalidatetarget:
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj);
crt->target=NULL; crt->pathn=0;
goto donemove;
revalidatetargetok:
//STEP 3: CAST
//after casting if nothing else is possible we go back to the enumeration phase
//have target!
//attack with a spell?
//crt spell
//in range?
x2=crt->target->x; y2=crt->target->y;
if (crt->cast){
if (stormcloakcheck(x,y)) goto crtcantcast;
crt_casti=rnd*8;
crt->cast=NULL;
x4=myobj->type&1023;
//summon! KXC
x3=0;
if ((x4==411)&&((crt_casti&1)==1)) x3=1; //dragon
if (x3){ //75% change of unselecting spell
x3=rnd*4;
if (x3) x3=0; else x3=1;
}
if (x3){
if (crt->mp>=8){ crt->mp-=8; //mp
x3=rnd*3; x3--; y3=rnd*3; y3--;
x3+=x; y3+=y;
if ((bt[y3][x3]>>10)&1){
myobj3=OBJnew();
myobj3->type=367; //daemon!
myobj3->more=malloc(sizeof(creature));
ZeroMemory(myobj3->more,sizeof(creature));
crt=(creature*)myobj3->more;
crt->crt_struct=TRUE;
crt->hp=(obji[sprlnk[myobj3->type&1023]].v8>>8)*4;
crt->mp=rnd*9;
crt->al=1;
x4=rnd*4; if (x4==0) crt->al=4; //25% chance of good allegiance!
crt->respawn_x=1024; //seconds till spawned crt will disappear
myobj9=OBJnew(); myobj9->type=188; crt->items=myobj9; //(not included)bag
myobj3->info|=4; //<-crt
OBJadd(x3,y3,myobj3);
crt->wait+=1.0f+rnd*1.0f; goto donemove;
}//land passable
}//mp
}//x3==1 summon
x3=0; //invisibility! SL
if ((x4==367)&&((crt_casti&2)==2)) x3=1; //deamon
if (x4==352) x3=1; //ghost
if (x3){
if (crt->mp>=5){ crt->mp-=5; //mp
i3=SFnew(x,y); //destination is more important than the source
sf[i3].type=19;
sf[i3].x=x;
sf[i3].y=y;
sf[i3].x2=x;
sf[i3].y2=y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
crt->flags|=2;
crt->wait+=1.0f+rnd*1.0f; goto donemove;
}//mp
}//x3==1, invisibility done
//type 2: direct attack spells
if ((abs(x-x2)<=8)&&(abs(y-y2)<=8)){ //in spell range!
if (OBJcheckbolt(x,y,x2,y2)==NULL){ //not blocked
if (stormcloakcheck(x2,y2)) goto crtcantcast;
//paralyze! AXP
x3=0;
if ((x4==362)&&((crt_casti&1)==1)) x3=1; //winged gargoyle
if (x3){ //50% change of unselecting spell
x3=rnd*2;
if (x3) x3=0; else x3=1;
}
if ((x4==378)&&((crt_casti&2)==2)) x3=1; //mage
if (x3){
if (target_struct==2){
if (tnpc->wait_disable) goto already_paralyzed;
}
if (crt->mp>=5){ crt->mp-=5; //mp
i3=SFnew(x2,y2); //destination is more important than the source
sf[i3].type=14; //blue ball
sf[i3].x=x;
sf[i3].y=y;
sf[i3].x2=x2;
sf[i3].y2=y2;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x3=obji[sprlnk[myobj->type&1023]].v7&255;
x3/=4;
x3=x3+(rnd*x3);
if (target_struct==2){
if (x3){
tnpc->wait_disable+=x3;
tnpc->flags|=8; //paralyzed
if (tnpc->player){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," paralyzed!"); NET_send(NETplayer,tnpc->player->net,t);
}
}
}else{
tnpc->wait_walk+=x3;
}
crt->wait+=1.0f+rnd*1.0f; goto donemove;
}//mp
}//x3==1 paralyze
already_paralyzed:
//lightning! OG
x3=0;
if ((x4==347)&&((crt_casti&1)==0)) x3=1; //reaper
if ((x4==362)&&((crt_casti&1)==0)) x3=1; //winged gargoyle
if (x4==355) x3=1; //gazer
if ((x4==378)&&((crt_casti&1)==0)) x3=1; //mage
if ((x4==369)&&((crt_casti&1)==0)) x3=1; //drake
if (x3){
if (crt->mp>=5){ crt->mp-=5; //mp
i3=SFnew(x2,y2); //destination is more important than the source
sf[i3].type=5; //wand
sf[i3].x=x;
sf[i3].y=y;
sf[i3].x2=x2;
sf[i3].y2=y2;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
if (tnpc->lev==1 && (tnpc->exp<1600)){
goto donemove;
}
x3=rnd*(48);
//it should do same damage as player lightning spell and armour definelty doesn't reduce the damage it didn't in U6 so why it should in u6o.
//maybe armour should reduce some damage, but definetly not much.
//x3=rnd*(16+((obji[sprlnk[myobj->type&1023]].v7&255)/2));
//x3=rnd*(obji[sprlnk[myobj->type&1023]].v7&255);
if (target_struct==2) x5=rnd*(tnpc->arm+1); else x5=rnd*((obji[sprlnk[crt->target->type&1023]].v7>>8)+1+1+getequiparmourvalue((object*)crt2->items->more));
x3-=x5/4; if (x3<0) x3=0; //npc armour!
//repel!
//if (target_struct==2) x5=rnd*tnpc->i; else x5=rnd*(obji[sprlnk[crt->target->type&1023]].v7&255);
//x6=rnd*(32+4*5);
//if (x5>=x6) x3=0;
if (x3){
tnpc->hp-=x3;
if (target_struct==2){
tnpc->upflags|=2; //hp
}else{//target_struct!=2
if (tnpc->flags&4){ //wake creature if asleep!
((creature*)tnpc)->wait=0;
if (tnpc->flags&8) tnpc->flags-=8; //unparalyze //1=poison, 2=invisible, 4=asleep, 8=paralyzed
if (tnpc->flags&4) tnpc->flags-=4; //awaken //1=poison, 2=invisible, 4=asleep, 8=paralyzed
}//wake creature if asleep!
}//target_struct==2
i3=SFnew(x2,y2);
sf[i3].type=1; //attack
sf[i3].x2=x3;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
}
crt->wait+=1.0f+rnd*1.0f; goto donemove;
}//mp
}//x3==1
//lightning done
//magic arrow! OJ
x3=0;
if ((x4==347)&&((crt_casti&1)==1)) x3=1; //reaper
if ((x4==367)&&((crt_casti&1)==0)) x3=1; //deamon
if (x4==345) x3=1; //squid
if ((x4==369)&&((crt_casti&1)==0)) x3=1; //drake
if (x3){
if (crt->mp>=2){ crt->mp-=2; //mp
i3=SFnew(x2,y2); //destination is more important than the source
sf[i3].type=2;
sf[i3].x=x;
sf[i3].y=y;
sf[i3].x2=x2;
sf[i3].y2=y2;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
if (tnpc->lev==1 && tnpc->exp<1600){
goto donemove;
}
x3=rnd*24;
//x3=rnd*(8+((obji[sprlnk[myobj->type&1023]].v7&255)/4));
//x3=rnd*((obji[sprlnk[myobj->type&1023]].v7&255)/2);
if (target_struct==2) x5=rnd*(tnpc->arm+1); else x5=rnd*((obji[sprlnk[crt->target->type&1023]].v7>>8)+1+1+getequiparmourvalue((object*)crt2->items->more));
x3-=x5/4; if (x3<0) x3=0; //npc armour!
//repel!
//if (target_struct==2) x5=rnd*tnpc->i; else x5=rnd*(obji[sprlnk[crt->target->type&1023]].v7&255);
//x6=rnd*(32+4*2);
//if (x5>=x6) x3=0;
if (x3){
tnpc->hp-=x3;
if (target_struct==2) tnpc->upflags|=2; //hp
i3=SFnew(x2,y2);
sf[i3].type=1; //attack
sf[i3].x2=x3;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
}
crt->wait+=1.0f+rnd*1.0f; goto donemove;
}//mp
}//x3==1
//magic arrow done
x3=0; //fireball! PF
if (x4==346) x3=1; //sea serpant
if ((x4==411)&&((crt_casti&1)==0)) x3=1; //dragon
if ((x4==369)&&((crt_casti&1)==1)) x3=1; //drake
if ((x4==367)&&((crt_casti&1)==1)) x3=1; //deamon
if ((x4==378)&&((crt_casti&1)==1)) x3=1; //mage
if (x3){
if (crt->mp>=3){ crt->mp-=3; //mp
i3=SFnew(x2,y2); //destination is more important than the source
sf[i3].type=8;
sf[i3].x=x;
sf[i3].y=y;
sf[i3].x2=x2;
sf[i3].y2=y2;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
if (tnpc->lev==1 && tnpc->exp<1600){
goto donemove;
}
x3=rnd*32;
//x3=rnd*(12+((obji[sprlnk[myobj->type&1023]].v7&255)/3));
//x3=rnd*((obji[sprlnk[myobj->type&1023]].v7&255)*24/32);
//txtnumint(t5,tnpc->arm);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
if (target_struct==2) x5=rnd*(tnpc->arm+1); else x5=rnd*((obji[sprlnk[crt->target->type&1023]].v7>>8)+1+1+getequiparmourvalue((object*)crt2->items->more));
x3-=x5/4; if (x3<0) x3=0; //npc armour!
//repel!
//if (target_struct==2) x5=rnd*tnpc->i; else x5=rnd*(obji[sprlnk[crt->target->type&1023]].v7&255);
//x6=rnd*(32+4*3);
//if (x5>=x6) x3=0;
if (x3){
tnpc->hp-=x3;
if (target_struct==2) tnpc->upflags|=2; //hp
i3=SFnew(x2,y2);
sf[i3].type=1; //attack
sf[i3].x2=x3;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
}
crt->wait+=1.0f+rnd*1.0f; goto donemove;
}//mp
}//x3==1
//fireball done
}//not blocked
}//in spell range
}//castnow!
crtcantcast:
if ((abs(x-x2)<=1)&&(abs(y-y2)<=1)){ //close ->attack
//lower hp of target
//tnpc=(npc*)crt->target->more; THERE IS NO PURPOSE FOR THIS LINE OF CODE!
if (target_struct==2) x5=rnd*(tnpc->arm+1); else x5=rnd*((obji[sprlnk[crt->target->type&1023]].v7>>8)+1+1+getequiparmourvalue((object*)crt2->items->more));
//x5=rnd*(tnpc->arm+1);
//x6=rnd*((obji[sprlnk[myobj->type&1023]].v5/2+1)+1);
//old
//x6=rnd*((obji[sprlnk[myobj->type&1023]].v5>>2)+1);
//enemies have the same deficiets on their attacks as players
//x6=rnd*(((obji[sprlnk[myobj->type&1023]].v8&255)+1)*2+1)-((obji[sprlnk[myobj->type&1023]].v8&255)+1);
//damage enemy can do
//x6=rnd*((obji[sprlnk[myobj->type&1023]].v8&255)+1+1); ***LATEST***
x6=obji[sprlnk[myobj->type&1023]].v8&255;
//GPF!
//if (((object*)crt->items)==NULL) exit( 789);
x7=getequiph2hwepdamage((object*)crt->items->more);
if (x7>x6){
//txtnumint(t7,x6);
//txtadd(t7,"->");
//txtnumint(t8,x7);
//txtadd(t7,t8);
//MessageBox(NULL,t7->d,"Ultima 6 Online",MB_OK);
x6=x7;
}
x6++;
x6=rnd*x6;
x6-=x5;
static unsigned char crtatt_damage=0;
crtatt_damage=0;
if (x6>0){ //attack will do damage!
//can NPC dodge the attack?
//generate rnd number up to ?
//if its not 0 you dodged the attack!
//even with dex 64 you still get hit half the time!!!
//generate 2 random numbers
//m is 0-31
//d is 0-tnpc->d
//if d is larger than m you dodged the attack
//if you have 32 dex you'll dodge half attacks on average
//if you have 64 dex you'll dodge all attacks on average!!
//currently 32 dex only dodges 1/4 of attacks
x7=rnd*32; //0-127
if (target_struct==2) x8=rnd*(tnpc->d+1); else x8=rnd*((obji[sprlnk[crt->target->type&1023]].v6>>8)+1);
//if (int(rnd*32)<=int(rnd*((obji[sprlnk[myobj2->type&1023]].v6>>8)+1))){
if (x7>x8){ //couldn't dodge the attack!
tnpc->hp-=x6;
crtatt_damage=1;
//poison target?
x5=myobj->type&1023;
x7=0;
if (x5==354) x7=1; //mouse
if (x5==342) x7=1; //rat
if (x5==360) x7=1; //rotworms
if (x5==426) x7=1; //scorp
if (x5==413) x7=1; //silver serp
if (x5==375) x7=1; //slime
if (x5==358) x7=1; //snake
if (x5==361) x7=1; //spider
if (x5==345) x7=1; //squid
if (x7){
x7=rnd*32;
if (x7==0){
if (target_struct==2){
if (tnpc->player){
if ((tnpc->flags&1)==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," poisoned!"); NET_send(NETplayer,tnpc->player->net,t);
}//flags&1
}//player
tnpc->upflags|=2; //hp
}//2
tnpc->flags|=1; //poison NPC
}//x7==0
}//x7
if ((myobj->type&1023)==357){ //corpser
x7=rnd*16;
if (x7==0){
if (target_struct==2){
if (tnpc->player){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," dragged under!"); NET_send(NETplayer,tnpc->player->net,t);
}//player
}//2
tnpc->hp=tnpc->hp>>1;
crt->wait+=8.0f;
}//x7
}//357
//txtnumint(t5,x6);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
}
}
//unsigned long upflags; //update NPC flags
//1 name, portriat, str, dex, int, lev, hp_max, mp_max
//2 hp
//4 mp
//8 xp
//16 weight (automatically set if inventory/equipped items change)
//32 inventory, bag icon
//64 equipped items
if (target_struct==2) tnpc->upflags|=2; //hp
i3=SFnew(x2,y2);
sf[i3].type=1; //attack
if (crtatt_damage==0) sf[i3].type=16;
sf[i3].x=x2;
sf[i3].x2=0; if (crtatt_damage) sf[i3].x2=x6;
sf[i3].y=y2;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
//change direction
OBJdir(myobj,x2,y2);
f=(float)(obji[sprlnk[myobj->type&1023]].v6>>8)/64.0f; if (f>1) f=1;
crt->wait+=2.0-(f*0.25f);
//crt->wait+=1.0f;
} //close
else{ //far ->move towards
if ((myobj->type&1023)==365){ //tanglevine
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0; goto donemove;
}
if ((myobj->type&1023)==347){ //reaper
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0; goto donemove;
}
x5=1; //flags
if ((myobj->type&1023)==345) x5=2; //squid
if ((myobj->type&1023)==346) x5=2; //sea serpent
if ((myobj->type&1023)==343) x5=3; //insects
if ((myobj->type&1023)==344) x5=3; //bat
if ((myobj->type&1023)==356) x5=3; //bird
if ((myobj->type&1023)==362) x5=3; //winged gargoyle
if ((myobj->type&1023)==369) x5=3; //drake
if ((myobj->type&1023)==372) x5=3; //mongbat
if ((myobj->type&1023)==373) x5=3; //wisp
if ((myobj->type&1023)==411) x5=3; //dragon
if ((myobj->type&1023)==352) x5=4; //GHOST (4=unlimited!)
if ((myobj->type&1023)==366){ //tanglevive tendril
x5=5;
x4=rnd*4; if (x4){
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
crt->pathn=0;
goto donemove;
}
}
/*
WPF_OBJECT=myobj; wpf_pathfind(tnpc->path,myobj->x,myobj->y,x2,y2,16,0,0);
if (WPF_RETURN==WPF_PATHFOUND){
if (WPF_PATHLENGTH){
tnpc->path_max=WPF_PATHLENGTH; tnpc->pathn=WPF_PATHLENGTH;
playerlist[tpl]->pathfind=1; //use pathfinding formula!
goto doneclmess;
}
playerlist[tpl]->pathfind=0; tnpc->path_max=0; tnpc->pathn=0;
}
}//party
*/
if (crt->pathn) goto crt_gotpath;
x4=32; if ((x>=1024)&&(!((y>=256)&&(x<1280)&&(y<512)))) x4=16;
WPF_NEXTTO=1; WPF_OBJECT=myobj; wpf_pathfind(crt->path,x,y,x2,y2,x4,x5,0);
//SPECIAL NOTE: REAPER AND TANGLEVINE SKIP THE ABOVE LINE OF CODE
x4=0;
if (WPF_RETURN==WPF_PATHFOUND){
if (WPF_PATHLENGTH){
x4=1;
if (WPF_PATHLENGTH>4) WPF_PATHLENGTH=4;
crt->path_max=WPF_PATHLENGTH; crt->pathn=WPF_PATHLENGTH;
}
}
if (x4==0){
//PATHFIND_NEXTTO=1; x4=pathfind(crt->path,x,y,x2,y2,x5);
//x5=28+4; if ((x2>=1024)&&(y2<256)) x5=16;
//if ((x4==0)||(x4>x5)){
crt->pathn=0;
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0;
x2=rnd*4; x3=x; y3=y;
if (x2==0) x3--;
if (x2==1) x3++;
if (x2==2) y3--;
if (x2==3) y3++;
goto crt_walk; //wander
}
crt_gotpath:
x3=x; y3=y;
/*
if (crt->path[0]==PFright) x3++;
if (crt->path[0]==PFleft) x3--;
if (crt->path[0]==PFup) y3--;
if (crt->path[0]==PFdown) y3++;
*/
if (crt->path[crt->path_max-crt->pathn]==PFright) x3++;
if (crt->path[crt->path_max-crt->pathn]==PFleft) x3--;
if (crt->path[crt->path_max-crt->pathn]==PFup) y3--;
if (crt->path[crt->path_max-crt->pathn]==PFdown) y3++;
crt->pathn--;
crt_walk:
if ((myobj->type&1023)==366){ //tendril
if (abs(x3-crt->respawn_x)>=24){
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
goto donemove;
}
if (abs(y3-crt->respawn_y)>=24){
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
goto donemove;
}
}
if ((myobj->type&1023)==365){
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0; goto donemove;
} //tanglevine
if ((myobj->type&1023)==347){
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0; goto donemove;
} //reaper
if (OBJmove2(myobj,x3,y3)){ //blocked!
f=0.5f+rnd*0.5f; if (crt->wait<f) crt->wait=f;
VLNKsremove(myobj); crt->target=NULL; crt->pathn=0; goto donemove;
}
f=(float)(obji[sprlnk[myobj->type&1023]].v6>>8)/64.0f; if (f>1.0f) f=1.0f;
crt->wait+=(0.125f+0.25f-0.0625f-f*0.125);
} //move towards
} //wait
} //alive check
} //crt!=NULL
goto donemove;
} //crt
i3=0;
//if ((i2>=376)&&(i2<=387))i3=1;
//if ((i2>=409)&&(i2<=410))i3=1;
if (myobj->info&2) i3=1; //2003 has NPC struct
if (i3==1){//NPC type (player/partymember/NPC)
tnpc=(npc*)myobj->more;
if (tnpc){ //tnpc!=NULL
//walk
f=et;
if (tnpc->wait_attack||tnpc->wait_cast) f=et/2.0f;
if (tnpc->wait_attack&&tnpc->wait_cast) f=et/3.0f;
//cast
f2=et;
if (tnpc->wait_walk||tnpc->wait_attack) f2=et/1.333333f;
if (tnpc->wait_walk&&tnpc->wait_attack) f2=et/1.666666f;
//attack
f3=et;
if (tnpc->wait_walk||tnpc->wait_cast) f3=et/1.333333f;
if (tnpc->wait_walk&&tnpc->wait_cast) f3=et/1.666666f;
if (tnpc->horse){
if (tnpc->player->craft==NULL){
//walk
f=et;//walk speed is never slowed by other activities
//cast
f2=et;
if (tnpc->wait_attack) f2=et/1.333333f;
//attack
f3=et;
if (tnpc->wait_cast) f3=et/1.333333f;
}//!craft
}//tnpc->horse
tnpc->wait_walk-=f; if (tnpc->wait_walk<0) tnpc->wait_walk=0;
f5=tnpc->wait_cast;
tnpc->wait_cast-=f2; if (tnpc->wait_cast<0) tnpc->wait_cast=0;
tnpc->wait_attack-=f3; if (tnpc->wait_attack<0) tnpc->wait_attack=0;
tnpc->wait_disable-=et; if (tnpc->wait_disable<0) tnpc->wait_disable=0;
if (tnpc->flags&8){
if (tnpc->wait_disable==0){
tnpc->flags-=8;
if (tnpc->player){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," free!"); NET_send(NETplayer,tnpc->player->net,t);
}
}
}
tplayer=tnpc->player;
if (tplayer){
if (myobj2=tplayer->party[tplayer->selected_partymember]){
if (myobj==myobj2) goto npcactiondone; //selected partymember
}
f=0.5f; if (int((ett/f))!=int((ett/f)-(et/f))){
x2=rnd*8; if (!x2){
if (tnpc->command&(8+16)){ //heal
for (x2=0;x2<=7;x2++){
if (myobj2=tplayer->party[x2]){
tnpc2=(npc*)myobj2->more;
if ((tnpc->command&16)||(tnpc==tnpc2)){
if (tnpc2->hp<=(tnpc2->hp_max>>1)) goto castheal_selected;
}
}
}
goto castheal_done;
castheal_selected:
static object *castheal_target;
castheal_target=myobj2;
x2=((0<<4)+6); //heal
if (tnpc2->lev>=3){ //attempt a great heal
x2=((3<<4)+4); //great heal
}
castheal_retry:
tpx=myobj2->x; tpy=myobj2->y; x=0; y=0;
cast_spell=1; goto cast_spell0; //goto spell
cast_spell1: //return #1
if ((i2!=1)&&(i2!=3)){
if (castheal_target){
myobj2=castheal_target; tnpc2=(npc*)myobj2;
castheal_target=NULL;
x2=((0<<4)+6); //heal
goto castheal_retry;
}
}
castheal_target=NULL;
goto npcactiondone;
}//heal
castheal_done:
if (tnpc->command&(32+64)){ //cure
for (x2=0;x2<=7;x2++){
if (myobj2=tplayer->party[x2]){
tnpc2=(npc*)myobj2->more;
if ((tnpc->command&64)||(tnpc==tnpc2)){
if (tnpc2->flags&1) goto castcure_selected;
}
}
}
goto castcure_done;
castcure_selected:
tpx=myobj2->x; tpy=myobj2->y; x=0; y=0;
x2=((0<<4)+3); //cure
cast_spell=2; goto cast_spell0; //goto spell
cast_spell2: //return #2
goto npcactiondone;
}//cure
castcure_done:
if (tnpc->command&1){ //yellowpotion
if (tnpc->hp<=(tnpc->hp_max>>1)){ //hp half or less?
//scan inventory for a potion
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==(275+1024*2)){
tnpc->hp+=30; if (tnpc->hp>tnpc->hp_max) tnpc->hp=tnpc->hp_max;
tnpc->upflags|=2;
OBJremove(OBJlist_list[y6]);
tnpc->upflags|=32;
goto npcactiondone;
}//type
}//y6
}//hp
}//yellowpotion
if (tnpc->command&2){ //redpotion
if (tnpc->flags&1){ //poisoned
//scan inventory for a potion
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==(275+1024*1)){
tnpc->flags&=(65535-1); //remove poisoned flag
tnpc->upflags|=2;
OBJremove(OBJlist_list[y6]);
tnpc->upflags|=32;
goto npcactiondone;
}//type
}//y6
}//poisoned
}//redpotion
if (tnpc->command&4){ //eat
if (!tnpc->food){
x6=OBJlist((object*)tnpc->items->more); //x6=last object number
OBJlist_last=NULL;
for(y6=0;y6<x6;y6++){
x2=0;
x3=OBJlist_list[y6]->type&1023;
if (x3==95) x2=6; //95 grapes 3 B *6
if (x3==96) x2=1; //96 butter 1 C *1
if (x3==115) {x2=5; x5=1;} //115 wine 6 6 5 5 4 6 6 4 4 =5 C *5
if (x3==116) {x2=4; x5=1;} //116 mead 4 5 3 2 5 4 4 4 3 =4 C *4
if (x3==117) {x2=4; x5=1;} //117 ale 3 7 2 5 3 3 3 4 2 =4 C *4
if (x3==128) x2=12; //128 bread 3 3 (2 loaves) c A *12
if (x3==129) x2=16; //129 meat (legs) c 4 3 3 4 4 4 4 4 4 A *16
if (x3==130) x2=8; //130 rolls 1 2 2 A *m
if (x3==131) x2=12; //131 cake 8 5 B *12
if (x3==132) x2=10; //132 cheese 6 5 B *10
if (x3==133) x2=16; //133 ham (looks like steak) 3 5 A *16
if (x3==135) x2=28; //135 horse chops (gargoyle food) A *28
if (x3==179) {x2=2; x5=1;} //179 bucket of water *this item needs modifying after use (1) B *2
if (x3==180) {x2=8; x5=1;} //180 bucket of milk *this item needs modifying after use 3 5 =4 B *8
if (x3==184) x2=10; //184 jar of honey *this item needs modifying after use 10 C *10
if (x3==209) x2=12; //209 small hanging meat 6 B *12
if (x3==210) x2=28; //210 big hanging meat 9 6 A =7 *28
if (x3==265) x2=6; //265 fish 3 B *6
if (x2){
x2*=4;
tnpc->food=x2;
txtset(t,"?"); t->d2[0]=8; txtaddchar(t,255); txtadd(t,tnpc->name);
if (x5) txtadd(t," drinks the "); else txtadd(t," eats the ");
y2=objname[(OBJlist_list[y6]->type&1023)*2];
y3=objname[(OBJlist_list[y6]->type&1023)*2+1];
txtNEWLEN(t2,y3);
memcpy(&t2->d2[0],&objname2[y2],y3);
txtadd(t,t2); txtadd(t,".");
NET_send(NETplayer,tnpc->player->net,t);
tnpc->upflags|=32;
if (obji[sprlnk[OBJlist_list[y6]->type&1023]+(OBJlist_list[y6]->type>>10)].flags&4096){
if (OBJlist_list[y6]->more2!=1){ //more than 1!
OBJlist_list[y6]->more2--; goto npcactiondone;
}
}
if ((x3==179)||(x3==180)) {OBJlist_list[y6]->type=178; goto npcactiondone;}
if (x3==184) {OBJlist_list[y6]->type=183; goto npcactiondone;}
OBJremove(OBJlist_list[y6]);
goto npcactiondone;
}//x2
}//y6
}//food
}//eat
}//8
}//0.5
npcactiondone:
//$rate$
//x2=37+3*CONnpc2->lev;
//if ((CONnpc2->s+CONnpc2->d+CONnpc2->i)>x2) txtadd(t2,"16"); else txtadd(t2,"8");
//deduct gold
//1day=1hour of real time
if (tnpc->converse==201){
if ((tnpc->s+tnpc->d+tnpc->i)>(37+3*tnpc->lev)) f=24.0f; else f=8.0f;
f=4096.0f/f; if (int((ett/f))!=int((ett/f)-(et/f))){
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
if (tnpc3!=tnpc){
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}
}} //!=NULL,x6
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==88){ //gold
OBJlist_list[y6]->more2--;
if (!OBJlist_list[y6]->more2){
OBJremove(OBJlist_list[y6]);
OBJrelease(OBJlist_list[y6]);
}//more2
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
tnpc3->upflags|=32; //inv
}}
goto paidnpc;
}//88
}//y6
if (tplayer->GNPCflags[64]) tplayer->GNPCflags[64]--; //take payment from bank!
}//f
}//201
paidnpc:
if (f5&&(tnpc->wait_cast==0)){
//but which party member are we??
for (i4=0;i4<=7;i4++){
if (tplayer->party[i4]==myobj){
txtset(t,"??"); t->d2[0]=18; t->d2[1]=i4; NET_send(NETplayer,tplayer->net,t); //release cast icon!
}//==myobj
}//i4
}//f5&&(tnpc->wait_cast==0)
if (myobj2=(object*)myobj->prev){
/* MOONGATES MUST BE USED 2005
if (myobj2->type==(84+1024)){ //red gate
if (tplayer->party[0]==myobj){ //primary player
if (tplayer->selected_partymember==0){
i4=(myobj2->info&112)>>4;
if (i4==1){
for (i4=7;i4>=0;i4--){
if (tplayer->party[i4]!=NULL){
OBJremove(tplayer->party[i4]);
OBJadd(256+128-16,256+128+2,tplayer->party[i4]);
}
}
}//i4
}//partymember
}//==party[0]
}//red gate
if (myobj2->type==(85+1024)){ //moongate
if (tplayer->party[0]==myobj){ //primary player
if (tplayer->selected_partymember==0){
//move party, if not already at correct phase!
if (moonphase!=255){
if ((myobj->x!=moongatex[moonphase])||(myobj->y!=moongatey[moonphase])){
for (i4=7;i4>=0;i4--){
if (tplayer->party[i4]!=NULL){
OBJremove(tplayer->party[i4]);
OBJadd(moongatex[moonphase],moongatey[moonphase],tplayer->party[i4]);
}
}
}//x!= y!=
}//moonphase
}//partymember
}//==party[0]
}//moongate
*/
if (myobj2->type==172){ //spikes
f=0.5f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (tnpc->protection==0){
if (tnpc->hp) tnpc->hp--;
if (tnpc->hp) tnpc->hp--;
if (tnpc->hp) tnpc->hp--;
if (tnpc->hp) tnpc->hp--;
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=4;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
tnpc->upflags|=2; //hp
}//protection
}//f
}//spikes
if (myobj2->type==173){ //trap
if ((!myobj2->more2)||(myobj2->more2==tplayer->id)){
if (tnpc->protection==0){
for (x2=0;x2<=7;x2++){
if (tplayer->party[x2]==myobj){
if ((myobj->x==tplayer->trapx[x2])&&(myobj->y==tplayer->trapy[x2])) goto trap_alreadyhurt;
goto trap_gotpartymemberindex;
}
}
goto trap_alreadyhurt;
trap_gotpartymemberindex:
tplayer->trapx[x2]=myobj2->x; tplayer->trapy[x2]=myobj2->y;
if ((myobj2->info&(1<<9))==0){
OBJsave(myobj2->x,myobj2->y);
myobj2->info|=(1<<9); //make trap visible
}
x2=tnpc->hp>>2; if (!x2) x2=1; //-25% health
tnpc->hp-=x2;
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
tnpc->upflags|=2; //hp
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," wounded!"); NET_send(NETplayer,tplayer->net,t);
}//protection
}
}//trap
trap_alreadyhurt:
if (myobj2->type==320){ //sleep field
if ((myobj2->more2==tplayer->id)||(myobj2->more2==0)){
if ((tnpc->flags&4)==0){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (tnpc->protection==0){
tnpc->flags|=4; //asleep!
f=8.0f+rnd*24.0f; if (tnpc->wait_disable<f) tnpc->wait_disable=f;
}
}
}
}
}
if (myobj2->type==53){ //web paralyze player
if ((myobj2->more2==tplayer->id)||(myobj2->more2==0)){
if ((tnpc->flags&8)==0){
f=0.5f; if (int((ett/f))!=int((ett/f)-(et/f))){
x3=rnd*3;
if (x3==0){
f=4.0f+rnd*12.0f; if (tnpc->wait_disable<f) tnpc->wait_disable=f;
tnpc->flags|=8; //paralyzed
if (tnpc->player){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," is stuck in a web!"); NET_send(NETplayer,tnpc->player->net,t);
}
}
}
}
}
}
if (myobj2->type==318){ //poison field
if ((myobj2->more2==tplayer->id)||(myobj2->more2==0)){
if (tnpc->protection==0){
if ((tnpc->flags&1)==0){
tnpc->flags|=1; //poison NPC
tnpc->upflags|=2; //hp
}
}
}
}
if (myobj2->type==317){ //fire field -4hp/sec
if ((myobj2->more2==tplayer->id)||(myobj2->more2==0)){
f=0.5f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (tnpc->protection==0){
if (tnpc->hp) tnpc->hp--; //-2!
if (tnpc->hp) tnpc->hp--;
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=2;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
tnpc->upflags|=2; //hp
}
}//f
}//id
}//fire field
if ((myobj2->type&1023)==366){ //tanglevine tendril
f=0.5f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (tnpc->protection==0){
if (tnpc->horse==NULL){
if (tnpc->hp) tnpc->hp--;
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=1;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
tnpc->upflags|=2; //hp
}//not on horse
}
}//f
}//tanglevine tendril
//sleep field?
//concept when player first steps onto sleep field they fall asleep, but eventually they awake
//and have a brief oportunity to escape, before being put back to sleep again
//sleep usually lasts a very long and annoying time, like 16 seconds!
}
//experiential xp
f=256.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (tplayer->idle<=256){
if (tplayer->party[0]){
if ((object*)tplayer->party[0]->more==myobj){
tnpc->exp++; tnpc->upflags|=8;
}
}
}//idle
}
x=bt[myobj->y][myobj->x]&255;
if ((x>=3)&&(x<=6)){
if (tplayer->craft) goto poison_skip;
if (tnpc->horse) goto poison_skip;
if (tnpc->boots!=NULL){
if (tnpc->boots->type==28){
goto poison_skip;
}//->type!=SWAMPBOOTS
}//->boots!=NULL
if (tnpc->protection) goto poison_skip;
if ((tnpc->flags&1)==0){
tnpc->flags|=1; //poison NPC
tnpc->upflags|=2; //hp
}
poison_skip:;
}
if ((x>=221)&&(x<=223)){ //lava!
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if ((tnpc->protection==0)&&(tplayer->craft==NULL)){
x2=0;
if (x==221) x2=8;
if (x==222) x2=16;
if (x==223) x2=32;
tnpc->hp-=x2;
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
tnpc->upflags|=2; //hp
}//->protection==0
}
}
if (tnpc->flags&1){ //poisoned?
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (tnpc->lev==1 && tnpc->exp<1600){
if ((rnd*32.0f)<1.0f){
if (tplayer->party[0]){
if ((npc*)tplayer->party[0]->more==tnpc){
tnpc->flags&=(65535-1); //remove poisoned flag
tnpc->upflags|=2;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Inexperienced character's poison cured!"); NET_send(NETplayer,tplayer->net,t);
goto poisonremoved;
}
}
}
}
x=rnd*8; if (x==0) {
tnpc->hp--;
i3=SFnew(myobj->x,myobj->y);
sf[i3].type=1; //attack
sf[i3].x2=1;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
tnpc->upflags|=2;
}
}
}//poisoned
poisonremoved:
//horse food reduction
if (tnpc->horse){
f=60.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
x=rnd*180; if (x==0){
crt2=(creature*)tnpc->horse->more;
x=(crt2->respawn_x>>4)&3; if (x) x--;
crt2->respawn_x&=(0xFFFF-(3<<4));
crt2->respawn_x+=(x<<6);
}//x==0
}//f
}//->horse
if (tplayer->karma<=0){ if (tplayer->party[0]){ if ((npc*)tplayer->party[0]->more==tnpc){
tplayer->karma=0;
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))) {tnpc->hp--; tnpc->upflags|=2;}
}}}
//add mp
//x3=rnd*(32+(tnpc->i>>1)); //int can only double spell effectiveness!
if ((float)tnpc->i/4.0 >= 32.0) {
f=0.05f;
}else {
f=32.0f-((float)tnpc->i/4.0f);
}
if (int((ett/f))!=int((ett/f)-(et/f))) {
if (tnpc->mp!=tnpc->mp_max){
tnpc->mp++; if (tnpc->mp>tnpc->mp_max) tnpc->mp=tnpc->mp_max;
tnpc->upflags|=4;
}
}
//sleeping? WAKE UP!
if (tnpc->flags&4){
if (tnpc->wait_disable<=0){
tnpc->flags-=4;
}
}
//light ->~17min
//great light ->~68min
if (tnpc->light>=2){
f=32.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tnpc->light--;
}
}
if (tnpc->light==1) tnpc->light=0;
//tnpc->light=0;
//burn down torch?
//f=64.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (tnpc->wep_left!=NULL){
if (tnpc->wep_left->type==(90+1024)){
x=(tnpc->wep_left->info>>9)&15;
if (x==1){ //burn down
tnpc->wep_left=NULL;
tnpc->upflags|=64;
}else{
f=64.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (x==0) x=16;
x--; tnpc->wep_left->info&=(65535-(15<<9)); tnpc->wep_left->info|=(x<<9);
}
if (tnpc->light==0) tnpc->light=1;
}
}
}
if (tnpc->wep_right!=NULL){
if (tnpc->wep_right->type==(90+1024)){
x=(tnpc->wep_right->info>>9)&15;
if (x==1){ //burn down
tnpc->wep_right=NULL; tnpc->upflags|=64;
}else{
f=64.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
if (x==0) x=16;
x--; tnpc->wep_right->info&=(65535-(15<<9)); tnpc->wep_right->info|=(x<<9);
}
if (tnpc->light==0) tnpc->light=1;
}
}
}
//}//f64
//f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
//if (tnpc->flags&2) tnpc->flags-=2;
if (tnpc->protection){ //protection!
f=4.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tnpc->protection--; if (tnpc->protection==0) tnpc->upflags|=64; //update ->arm value
}
}
//NEWCODE
if (tnpc->negatemagic){ //negatemagic
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tnpc->negatemagic--;
}
}
//NEWCODEEND
//invisibility ring(s)
tnpc->flags&=(255-2);
if (tnpc->invisibility){
tnpc->flags|=2;
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
tnpc->invisibility--;
}
goto skipinvisrings;
}
if (tnpc->ring_left!=NULL){ if (tnpc->ring_left->type==258){ //invis
x=tnpc->ring_left->more2; if (x==0) x=64*4; //~4min
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))) x--;
tnpc->ring_left->more2=x;
if (x==0){
tnpc->ring_left=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s invisibility ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}else{tnpc->flags|=2; goto skipinvisrings;}
}}
if (tnpc->ring_right!=NULL){ if (tnpc->ring_right->type==258){
x=tnpc->ring_right->more2; if (x==0) x=64*4; //~4min
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))) x--;
tnpc->ring_right->more2=x;
if (x==0){
tnpc->ring_right=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s invisibility ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}else{tnpc->flags|=2;}
}}
skipinvisrings:
if (tnpc->flags&2){
if (tplayer->craft) tnpc->flags&=(255-2);
}
if (tnpc->ring_left!=NULL){ if (tnpc->ring_left->type==257){ //regeneration ring
if ((tnpc->hp>0)&&(tnpc->hp<tnpc->hp_max)){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
x=tnpc->ring_left->more2; if (x==0) x=128; //128hp
x--; tnpc->ring_left->more2=x;
tnpc->hp++; tnpc->upflags|=2;
if (x==0){
tnpc->ring_left=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s regeneration ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}
}//f
}//need hp
}}
if (tnpc->ring_right!=NULL){ if (tnpc->ring_right->type==257){ //regeneration ring
if ((tnpc->hp>0)&&(tnpc->hp<tnpc->hp_max)){
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
x=tnpc->ring_right->more2; if (x==0) x=128; //128hp
x--; tnpc->ring_right->more2=x;
tnpc->hp++; tnpc->upflags|=2;
if (x==0){
tnpc->ring_right=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s regeneration ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}
}//f
}//need hp
}}
//increase int as well attempt - Cear
if (tnpc->ring_right!=NULL)
{
if (tnpc->ring_right->type==257)//regeneration ring
{
if ((tnpc->mp>0)&&(tnpc->mp<tnpc->mp_max))
{
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f)))
{
x=tnpc->ring_right->more2; if (x==0) x=128; //128hp
x--; tnpc->ring_right->more2=x;
tnpc->mp++; tnpc->upflags|=4;
if (x==0)
{
tnpc->ring_right=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s regeneration ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}
}//f
}//need hp
}
}
if (tnpc->ring_left!=NULL)
{
if (tnpc->ring_left->type==257)//regeneration ring
{
if ((tnpc->mp>0)&&(tnpc->mp<tnpc->mp_max))
{
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f)))
{
x=tnpc->ring_left->more2; if (x==0) x=128; //128hp
x--; tnpc->ring_left->more2=x;
tnpc->mp++; tnpc->upflags|=4;
if (x==0)
{
tnpc->ring_right=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s regeneration ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}
}//f
}//need hp
}
}
if (tnpc->ring_left!=NULL){ if (tnpc->ring_left->type==256){ //protection ring
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
x=tnpc->ring_left->more2; if (x==0) x=4096; //~1hr
x--; tnpc->ring_left->more2=x;
if (x==0){
tnpc->ring_left=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s protection ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}
}//f
}}
if (tnpc->ring_right!=NULL){ if (tnpc->ring_right->type==256){ //
f=1.0f; if (int((ett/f))!=int((ett/f)-(et/f))){
x=tnpc->ring_right->more2; if (x==0) x=4096; //~1hr
x--; tnpc->ring_right->more2=x;
if (x==0){
tnpc->ring_right=NULL; tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t,"'s protection ring vanished!"); NET_send(NETplayer,tplayer->net,t);
}
}//f
}}
if (tnpc->food){//has food
f=16.0f;
//make fighters (high STR players) heal faster using food
//STR 16 is same, STR 48 is double
if (tnpc->s>16){
f2=tnpc->s;
f2=(f2-16.0f)/4.0f;
f-=f2;
}
if (int((ett/f))!=int((ett/f)-(et/f))){
tnpc->food--;
if (!tnpc->food){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," is hungry!"); NET_send(NETplayer,tplayer->net,t);
}
if (tnpc->hp<tnpc->hp_max) tnpc->hp++;
tnpc->upflags|=2;
}
}
//}//f1
}//tplayer
if (tplayer==NULL){ //NPC, not party member
if (tnpc->wait_walk==0){ //wait
if (tnpc->order==2){ //schedule
//*IMPORTANT* needs to check for nearest schedule, regardless of order,
//*MORE IMPORTANTLY* it needs to be day indepentant, reading a schedule from the prev
//day if necessary
//assuming a valid schedule exists...
x3=-1; f=btime+(bday*24-24);
SCHFND_retry:
f3=65536;
//find nearest prev schedule in the list
for (x2=0;x2<=31;x2++){ //find schedule
if (tnpc->schedule[x2].hour!=255){
f2=tnpc->schedule[x2].hour;
if (tnpc->schedule[x2].day){
f2+=(tnpc->schedule[x2].day*24-24); x4=1;
}else{
f2+=(bday*24-24); x4=0; //use current day
}
if (f2<f){
if ((f-f2)<=f3){
if(x4){
x3=x2;
}else{
if ((f-f2)<f3) x3=x2;
}//x4
f3=(f-f2); //new closest sch time
}//(f-f2)<=f3
}//f2<f
}//!=255
}//x2
if (x3==-1) {x3--; f=24*8; goto SCHFND_retry;}
if (x3==-2) goto NPC_skip1;
x2=x3;
tnpc->schedule_last=tnpc->schedule[x2].type;
if ((abs(myobj->x-tnpc->schedule[x2].x)==0)&&(abs(myobj->y-tnpc->schedule[x2].y)==0)){
tnpc->schedule_i=x2;
}
if (x2!=tnpc->schedule_i) tnpc->schedule_i=-1;
if (tnpc->schedule_i==x2){
if ((tnpc->schedule[x2].type==0x8F)||(tnpc->schedule[x2].type==0x90)){
//wander aimlessly!!!
if ((abs(myobj->x-tnpc->schedule[x2].x)<=4)&&(abs(myobj->y-tnpc->schedule[x2].y)<=4)){
x=rnd*4; x2=0; y2=0;
if (x==0) x2--;
if (x==1) x2++;
if (x==2) y2--;
if (x==3) y2++;
tnpc->wait_walk+=1.0f+rnd*2.0f;
tnpc->pathn=0; //clear pathfind
goto npc_walk; //walk randomly
}//<4
tnpc->schedule_i=-1;
}
}
/*
for (x2=0;x2<=31;x2++){ //find schedule
if (x2==31) goto gotschedule; //last index
if ((tnpc->schedule[x2].day==0)||(tnpc->schedule[x2].day==bday)){ //valid day
f=tnpc->schedule[x2].hour;
x3=1;
sch_sametimeday:
f2=tnpc->schedule[x2+x3].hour;
if (f2==255) goto gotschedule; //next index is NULL (use the current schedule)
if ((tnpc->schedule[x2+x3].day!=0)&&(tnpc->schedule[x2+x3].day!=bday)){x3++; goto sch_sametimeday;} //next sch is for a different day, ignore
if (f2==f) {x3++; goto sch_sametimeday;} //next sch is for the same time, ignore
if ((btime>=f)&&(btime<=f2)) goto gotschedule;
} //valid day
}//schedule 0-31 loop
goto NPC_skip1; //schedule not found ->exit
gotschedule: //index x2
if (btime<tnpc->schedule[x2].hour) NPC_skip1; //false schedule read by accident!
*/
//gotschedule:
//goto .x,.y
x3=myobj->x-tnpc->schedule[x2].x;
y3=myobj->y-tnpc->schedule[x2].y;
if ((x3==0)&&(y3==0)) goto NPC_skip1;
if (tnpc->pathn==0){
/*
tnpc->path_max=pathfind(tnpc->path,myobj->x,myobj->y,tnpc->schedule[x2].x,tnpc->schedule[x2].y,NULL);
//if (tnpc->path_max==0) tnpc->path_max=pathfind(tnpc->path,myobj->x,myobj->y,tnpc->schedule[x2].x,tnpc->schedule[x2].y,NULL);
if (tnpc->path_max==0){ tnpc->pathn=0; tnpc->wait_walk+=1.0f+rnd*2.0f; goto NPC_skip1;}
tnpc->pathn=tnpc->path_max;
*/
/*
z=abs(myobj2->x-myobj->x); z2=abs(myobj2->y-myobj->y); if (z2>z) z=z2;
z+=32; if (z>250) z=250;
WPF_OBJECT=myobj; wpf_pathfind(tnpc->path,myobj->x,myobj->y,myobj2->x,myobj2->y,z,0,1);//|1|PATHFIND THROUGH OWN PARTY+16
if (WPF_RETURN==WPF_PATHFOUND){
if (WPF_PATHLENGTH){
tnpc->path_max=WPF_PATHLENGTH; tnpc->pathn=WPF_PATHLENGTH;
goto follow_getpath;
}
}
*/
/*
x3=abs(tnpc->schedule[x2].x-myobj->x); y3=abs(tnpc->schedule[x2].y-myobj->y); if (y3>x3) x3=y3;
x3+=32;
//if (x2>250) exit2(55);
if (x3>250){
txtnumint(t5,tnpc->converse); MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
tnpc->pathn=0; tnpc->wait_walk+=1.0f+rnd*2.0f; goto NPC_skip1;
}
*/
//if (x3>dv) dv=x3;
x3=abs(tnpc->schedule[x2].x-myobj->x); y3=abs(tnpc->schedule[x2].y-myobj->y); if (y3>x3) x3=y3;
x3+=64;
if (x3>250){
x3=250;
}
WPF_OBJECT=myobj; wpf_pathfind(tnpc->path,myobj->x,myobj->y,tnpc->schedule[x2].x,tnpc->schedule[x2].y,x3,0,4);
if (WPF_RETURN==WPF_NOPATHFOUND){
tnpc->pathn=0; tnpc->wait_walk+=1.0f+rnd*2.0f; goto NPC_skip1;
}
tnpc->path_max=WPF_PATHLENGTH; tnpc->pathn=WPF_PATHLENGTH;
}
//path
x2=0; y2=0;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFright) x2=1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFleft) x2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFup) y2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFdown) y2=1;
if (tnpc->pathn>0) { //fix for pathfinding crash.
tnpc->pathn--;
}
npc_walk:
myobj2=OBJfindlastall(myobj->x,myobj->y);
x3=OBJmove2(myobj,myobj->x+x2,myobj->y+y2);
if (myobj2!=NULL){
if (((myobj2->type&1023)==301)&&(x3==0)){ //close door behind NPC
myobj2=OBJfindlast(myobj2->x,myobj2->y);
if (myobj2!=NULL){
x2=myobj2->type&1023;
if ((x2>=297)&&(x2<=300)){
//assume not locked
x=myobj2->type>>10;
if (x&1) {myobj3=myobj2; myobj2=(object*)myobj2->more;} else {myobj3=(object*)myobj2->more;}
if (x<4){
x=x>>1;
x=x<<1;
x=x&2;
myobj2->type=x2+((x+4)*1024);
myobj3->type=x2+((x+5)*1024);
OBJcheckflags(myobj2->x,myobj2->y); OBJcheckflags(myobj3->x,myobj3->y);
}else{
x=x>>1;
x=x<<1;
x=x&2;
myobj2->type=x2+(x*1024);
myobj3->type=x2+((x+1)*1024);
OBJcheckflags(myobj2->x,myobj2->y); OBJcheckflags(myobj3->x,myobj3->y);
} //<4
x2=myobj2->x; y2=myobj2->y;
i3=SFnew(x2,y2);
//i3 points to new sf
sf[i3].type=4;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=1.0f; //NULL
sf[i3].more=2;
tnpc->wait_walk+=0.0625f;
tnpc->wait_walk+=(rnd*0.125f);
}
}
}//close door
}//!=NULL
if (x3){ //blocked
myobj2=myobj;
if (myobj3=OBJfindlast(myobj2->x+x2,myobj2->y+y2)){
//nonplayernpc->horse swap
if ((myobj3->type&1023)==431){
if (myobj3->info&8){//S->H(back)
myobj4=(object*)myobj3->more;
tnpc2=(npc*)myobj4->more;
x3=myobj4->x; y3=myobj4->y;
x4=0; y4=0;
//check adjacent squares of horse's head for walkability
if (bt[y3-1][x3]&1024){//walkable
x4=x3; y4=y3-1;
}
if (bt[y3][x3+1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3+1; y4=y3;}
x5=rnd*2; if (x5){x4=x3+1; y4=y3;}
}
if (bt[y3+1][x3]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3; y4=y3+1;}
x5=rnd*2; if (x5){x4=x3; y4=y3+1;}
}
if (bt[y3][x3-1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3-1; y4=y3;}
x5=rnd*2; if (x5){x4=x3-1; y4=y3;}
}
if (x4||y4){
OBJmove_allow=TRUE;
OBJmove2(myobj2,myobj3->x,myobj3->y);
OBJmove2(myobj4,x4,y4);
OBJmove_allow=FALSE;
goto doneswap2;
}
//if no adjacent square is available then move on top of the back of the horse
OBJmove_allow=TRUE;
OBJmove2(myobj2,myobj3->x,myobj3->y);
OBJmove_allow=FALSE;
goto doneswap2;
}
//else S->H(front)
//S->H(front)
myobj4=myobj3;
tnpc2=(npc*)myobj4->more;
x3=((object*)tnpc2->more)->x; y3=((object*)tnpc2->more)->y;
//if (x3==0) goto badhorseswap;
x4=0; y4=0;
//check adjacent squares of horse's head for walkability
if (bt[y3-1][x3]&1024){//walkable
x4=x3; y4=y3-1;
}
if (bt[y3][x3+1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3+1; y4=y3;}
x5=rnd*2; if (x5){x4=x3+1; y4=y3;}
}
if (bt[y3+1][x3]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3; y4=y3+1;}
x5=rnd*2; if (x5){x4=x3; y4=y3+1;}
}
if (bt[y3][x3-1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3-1; y4=y3;}
x5=rnd*2; if (x5){x4=x3-1; y4=y3;}
}
if (x4||y4){
OBJmove_allow=TRUE;
OBJmove2(myobj2,myobj4->x,myobj4->y);
OBJmove2(myobj4,x3,y3); OBJmove2(myobj4,x4,y4);
OBJmove_allow=FALSE;
goto doneswap2;
}
//if no adjacent square is available a regular swap will occur...
}//horse swap
//badhorseswap:
if (myobj3->info&(2+4)){ //swap with npc/crt
if (tnpc->converse==130){ //smith
tnpc->wait_walk+=1.0f+rnd*2.0f; //wait to reduce code overhead
tnpc->pathn=0; //path was blocked but another path may exist!
goto NPC_skip1;
}
//if ((myobj2->type&1023)==354){ //mouse
if (myobj4=OBJfindlastall(myobj2->x,myobj2->y)){
if ((myobj4->type&1023)==213) goto NPC_skip1; //mousehole
}
if (myobj4=OBJfindlastall(myobj2->x,myobj2->y)){
if (myobj4=(object*)myobj4->prev){
if (((myobj4->type&1023)==310)&&(myobj4->type&1024)) goto NPC_skip1; //portcullis
}
}
if (myobj4=OBJfindlastall(myobj2->x+x2,myobj2->y+y2)){
if ((myobj4->type&1023)==213) goto NPC_skip1; //mousehole
}
if (myobj4=OBJfindlastall(myobj2->x+x2,myobj2->y+y2)){
if (myobj4=(object*)myobj4->prev){
if (((myobj4->type&1023)==310)&&(myobj4->type&1024)) goto NPC_skip1; //portcullis
}
}
//}//mouse
//swap with NPC
x2=myobj2->x; y2=myobj2->y;
x3=myobj3->x; y3=myobj3->y;
//if ((abs(myobj->x-tnpc->schedule[x2].x)==0)&&(abs(myobj->y-tnpc->schedule[x2].y)==0)){
//tnpc->schedule_i=x2;
//if (schedule_i==0x91){
x4=1; //bedswap2
if (myobj3->info&2){
tnpc2=(npc*)myobj3->more;
if (tnpc2->schedule){ if (tnpc2->schedule_i!=-1){ if (tnpc2->schedule[tnpc2->schedule_i].type==0x91){ x4=0;}}}
if (tnpc2->converse==130) x4=0; //smith (other npc cannot swap with smith)
}
if (x4){
//myobj4=od[y3][x3]; if ((myobj4->type&1023)!=163){ //bedswap
OBJmove_allow=TRUE;
OBJmove2(myobj2,x3,y3);
OBJmove2(myobj3,x2,y2);
OBJmove_allow=FALSE;
doneswap2:
tnpc->wait_walk+=0.0625f; //regular move minimum wait
//tnpc->wait+=(rnd*0.125f);
tnpc->wait_walk+=(rnd*1.0f); //+swap wait
//tnpc->pathn++; //failed to move
if (myobj3->info&2) tnpc2->pathn=0; //other NPC's path needs updating
goto NPC_skip1;
} //bedswap2
}//<-npc
//}
}//!=NULL
//blocked! by a passthrough? ->use
myobj2=OBJfindlast(myobj->x+x2,myobj->y+y2);
if (myobj2!=NULL){
x3=myobj2->type;
//if ((x2==278)||(x2==280)){
if (x3==OBJ_PASSTHROUGH_V){ //v-passthrough
if (myobj2->more==NULL){
myobj2->more=OBJnew();
myobj3=(object*)myobj2->more;
myobj3->more=myobj2; //back link
myobj3->type=OBJ_PASSTHROUGH_V+1*1024;
OBJadd(myobj2->x-1,myobj2->y-1,myobj3);
}
else
{
OBJadd(myobj2->x-1,myobj2->y-1,(object*)myobj2->more);
}
x=myobj2->x;
y=myobj2->y-1;
OBJremove(myobj2);
myobj2->type=OBJ_PASSTHROUGH_V+2*1024;
OBJadd(x,y,myobj2);
tnpc->wait_walk+=0.0625f;
tnpc->wait_walk+=(rnd*0.125f);
tnpc->pathn++; //failed to move
goto NPC_skip1;
}//278
if (x3==OBJ_PASSTHROUGH_H){ //h-passthrough
if (myobj2->more==NULL){
myobj2->more=OBJnew();
myobj3=(object*)myobj2->more;
myobj3->more=myobj2; //back link
myobj3->type=OBJ_PASSTHROUGH_H+1*1024;
OBJadd(myobj2->x-1,myobj2->y-1,myobj3);
}
else
{
OBJadd(myobj2->x-1,myobj2->y-1,(object*)myobj2->more);
}
x=myobj2->x-1;
y=myobj2->y;
OBJremove(myobj2);
myobj2->type=OBJ_PASSTHROUGH_H+2*1024;
OBJadd(x,y,myobj2);
tnpc->wait_walk+=0.0625f;
tnpc->wait_walk+=(rnd*0.125f);
tnpc->pathn++; //failed to move
goto NPC_skip1;
}//280
}//myobj2
//blocked! by a door? ->use
myobj2=OBJfindlast(myobj->x+x2,myobj->y+y2);
if (myobj2!=NULL){
x3=myobj2->type&1023;
if ((x3>=297)&&(x3<=300)){
x2=x3;
//assume not locked
x=myobj2->type>>10;
if ((myobj2->type&1024)){//ignore the secondary door parts
if (x<8){
if (x&1) {myobj3=myobj2; myobj2=(object*)myobj2->more;} else {myobj3=(object*)myobj2->more;}
if (x<4){
x=x>>1;
x=x<<1;
x=x&2;
myobj2->type=x2+((x+4)*1024);
myobj3->type=x2+((x+5)*1024);
OBJcheckflags(myobj2->x,myobj2->y); OBJcheckflags(myobj3->x,myobj3->y);
}else{
x=x>>1;
x=x<<1;
x=x&2;
myobj2->type=x2+(x*1024);
myobj3->type=x2+((x+1)*1024);
OBJcheckflags(myobj2->x,myobj2->y); OBJcheckflags(myobj3->x,myobj3->y);
} //<4
x2=myobj2->x; y2=myobj2->y;
i3=SFnew(x2,y2);
//i3 points to new sf
sf[i3].type=4;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=1.0f; //NULL
sf[i3].more=1;
tnpc->wait_walk+=0.0625f;
tnpc->wait_walk+=(rnd*0.125f);
tnpc->pathn++; //failed to move
goto NPC_skip1;
}//x2<8
}
}
}
tnpc->wait_walk+=1.0f+rnd*2.0f; //wait to reduce code overhead
tnpc->pathn=0; //path was blocked but another path may exist!
goto NPC_skip1;
} //door
//f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
//tnpc->wait_walk+=(0.25f-0.0625f-f*0.125f);
//npc walk speed
//tnpc->wait_walk+=0.0625f;
//tnpc->wait_walk+=(rnd*0.125f);
tnpc->wait_walk+=(0.1875f+(rnd*0.0625f));
//tnpc->wait_walk+=(0.25f+(rnd*0.125f));
goto NPC_skip1;
} //order2
} //waitOK
goto NPC_skip1;
}
//have valid tplayer pointer! myobj=our object!
//if (tplayer->party[tplayer->selected_partymember]!=myobj){
//tplayer is valid
static unsigned char horse_movediagonal;
static short horse_movediagonalx,horse_movediagonaly;
horse_movediagonal=0;
//dv++;
//dv=tnpc->wait_walk;
//dv2=et/32.0f;
//tnpc->wait_walk-=(et/32.0f);
//if (tnpc->wait_walk<0) tnpc->wait_walk=0;
static unsigned char selected_partymember;
selected_partymember=0; if (tplayer->party[tplayer->selected_partymember]==myobj) selected_partymember=1;
if ((selected_partymember)&&(keyon[VK_SPACE]&&U6O_DEBUG)) tnpc->wait_walk=0;
//partymember npc
//AUTOPICKUPadd(myobj,myobj3);
//check surrounding squares for items to pickup
if (tnpc->wait_disable==0.0f){
if (tnpc->wait_attack==0.0f){
for (y2=-1;y2<=1;y2++){ for (x2=-1;x2<=1;x2++){ if (x2||y2){
//autopickupcheckloop:
if (myobj3=OBJfindlast(myobj->x+x2,myobj->y+y2)){
if (AUTOPICKUP_OBJECTVALID[myobj3->type&1023]){
if (myobj4=AUTOPICKUPcheck(tplayer,myobj3)){
//MessageBox(NULL,"myobj4 could have been recovered","Ultima 6 Online",MB_OK);
OBJremove(myobj3);
tnpc3=(npc*)myobj4->more;
static object *invbag,*invobj;
invbag=tnpc3->items;
invobj=myobj3;
//inventory add
txtsetchar(t,2);//sfx message
txtaddshort(t,1);//number of sfx effects
txtaddshort(t,27);//inventory add
txtaddshort(t,myobj4->x);//x
txtaddshort(t,myobj4->y);//y
txtaddshort(t,myobj3->type);//graphic (x2)
txtaddshort(t,0);//unused placeholder for y2
txtaddshort(t,0);//unused placeholder for more
txtaddfloat(t,0.25f);//time to display message for (in this case half a second)
NET_send(NETplayer,tplayer->net,t);
tnpc3->upflags|=32;//inv
//join/combine items in inventory
if (obji[sprlnk[invobj->type&1023]+(invobj->type>>10)].flags&4096){//multiple/stackable
if (myobj5=(object*)invbag->more){
joinitem2:
if (myobj5->type==invobj->type){//same type
if ((myobj5->info&128)==(invobj->info&128)){
if (((invobj->type&1023)==90)&&(myobj5->info!=invobj->info)) goto cantjoin2;//cant join half burnt torches
myobj5->more2+=invobj->more2;
OBJrelease(invobj);
goto joinitem_finished2;
}//same stealing type
}//same type
if (myobj5->next) {myobj5=(object*)myobj5->next; goto joinitem2;}
}//myobj5=(object*)invbag->more
}//4096
cantjoin2:
invobj->info|=112; invobj->next=invbag->more; invobj->prev=invbag; invbag->more=invobj; if (invobj->next) ((object*)invobj->next)->prev=invobj;
//autoready item?
if (obji[sprlnk[invobj->type&1023]].flags&8){
//check for any two handed weapons!
if (myobj5=tnpc3->wep_left){
if (obji[sprlnk[myobj5->type&1023]].flags&16) goto cantautoready;
}
if (myobj5=tnpc3->wep_right){
if (obji[sprlnk[myobj5->type&1023]].flags&16) goto cantautoready;
}
//ready item if possible
if (tnpc3->wep_left==NULL){
OBJremove(invobj);
tnpc3->wep_left=invobj;
tnpc3->upflags|=64;
goto autoreadycomplete;
}
if (tnpc3->wep_right==NULL){
OBJremove(invobj);
tnpc3->wep_right=invobj;
tnpc3->upflags|=64;
goto autoreadycomplete;
}
}//autoready item
autoreadycomplete:
cantautoready:
joinitem_finished2:
tnpc->wait_attack+=0.25f;
goto autopickup_gotitem;
}
}//AUTOPICKUP_OBJECTVALID
}
}}}
}//wait_attack
}//wait_disable
autopickup_gotitem:
//wizard eye movement
if (selected_partymember){
if (tplayer->wizardeyetimeleft){
x2=0; y2=0;
if ((tplayer->key&KEYleft)||(tplayer->key&KEYleft2)) x2--;
if ((tplayer->key&KEYright)||(tplayer->key&KEYright2)) x2++;
if ((tplayer->key&KEYup)||(tplayer->key&KEYup2)) y2--;
if ((tplayer->key&KEYdown)||(tplayer->key&KEYdown2)) y2++;
if (tplayer->key&KEYdown2) tplayer->key-=KEYdown2; //clear dir2 key
if (tplayer->key&KEYup2) tplayer->key-=KEYup2;
if (tplayer->key&KEYleft2) tplayer->key-=KEYleft2;
if (tplayer->key&KEYright2) tplayer->key-=KEYright2;
if (tplayer->wizardeyemovewait==0.0f){
tplayer->wizardeyemovewait=0.1f/0.8f;
if (x2||y2){
x2+=tplayer->wizardeyex; y2+=tplayer->wizardeyey;
//map boundries check
if (x2>=1){ if (y2>=1){ if (x2<2047){ if (y2<1023){
x3=1;
if ((bt[y2][x2]&255)>=252) x3=0;//cannot enter void!
if (x2>=0){ if (y2>=0){ if (x2<1024){ if (y2<1024){//britannia mainland
goto wizeye_norestriction;
}}}}
if (x2>=1024){ if (y2>=256){ if (x2<(1024+256)){ if (y2<512){//garg lands
goto wizeye_norestriction;
}}}}
//restricted area checks
if ((btflags[bt[y2][x2]&1023]&(1+2+4+8))==0){
//1=land passabe
//2=air passable
//4=sea passable
//8=bolt passable
x3=0;
}
wizeye_norestriction:
if (x3){
if (myobj2=od[y2][x2]){
wizeye_laddercheck:
myobj3=myobj2; if ((myobj3->info&8)==8) myobj3=(object*)myobj3->more;//redirector
x4=myobj3->type&1023;
if ((x4==305)||(x4==326)||(x4==308)){ //ladder or dungeon or hole
x2=myobj3->more2&0xFFFF;
y2=myobj3->more2>>16;
goto wizeye_gotladder;
}
if (myobj2->next){myobj2=(object*)myobj2->next; goto wizeye_laddercheck;}
}
wizeye_gotladder:
tplayer->wizardeyex=x2; tplayer->wizardeyey=y2;
}//x3
}}}}
}//x2||y2
}//f
goto dontmove;
}
}
if ((!tnpc->wait_walk)&&(!tnpc->wait_disable)){
if (selected_partymember){ //selected party member
x=0; x2=0; y2=0;
if ((tplayer->key&KEYleft)||(tplayer->key&KEYleft2)) x2--;
if ((tplayer->key&KEYright)||(tplayer->key&KEYright2)) x2++;
if ((tplayer->key&KEYup)||(tplayer->key&KEYup2)) y2--;
if ((tplayer->key&KEYdown)||(tplayer->key&KEYdown2)) y2++;
if (tplayer->key&KEYdown2) tplayer->key-=KEYdown2; //clear dir2 key
if (tplayer->key&KEYup2) tplayer->key-=KEYup2;
if (tplayer->key&KEYleft2) tplayer->key-=KEYleft2;
if (tplayer->key&KEYright2) tplayer->key-=KEYright2;
if (tnpc->horse&&(tplayer->craft==NULL)){//horse diagonal movement
//1. precheck all three related squares
if (x2&&y2){
x3=myobj->x+x2; y3=myobj->y+y2;
static unsigned char xok,yok,xyok; xok=0; yok=0; xyok=0;
if (bt[y3][x3]&1024){
//walkable
xyok=1;
}else{
//not walkable
//check if there is an npc to swap with
if (myobj3=OBJfindlast(x3,y3)){
if (myobj3->info&8) myobj3=(object*)myobj3->more;
if (myobj3->info&2) xyok=1;
}//myobj3
}//xy
if (bt[myobj->y][x3]&1024){
//walkable
xok=1;
}else{
//not walkable
//check if there is an npc to swap with
if (myobj3=OBJfindlast(x3,myobj->y)){
if (myobj3->info&8) myobj3=(object*)myobj3->more;
if (myobj3->info&2) xok=1;
}//myobj3
}//x
if (bt[y3][myobj->x]&1024){
//walkable
yok=1;
}else{
//not walkable
//check if there is an npc to swap with
if (myobj3=OBJfindlast(myobj->x,y3)){
if (myobj3->info&8) myobj3=(object*)myobj3->more;
if (myobj3->info&2) yok=1;
}//myobj3
}//y
if (xyok){
if (xok){
horse_movediagonal=1; horse_movediagonalx=0; horse_movediagonaly=y2;
y2=0;//mask y (it will be done on the second move)
goto horsemovepossible;
}
if (yok){
horse_movediagonal=1; horse_movediagonalx=x2; horse_movediagonaly=0;
x2=0;//mask x (it will be done on the second move)
goto horsemovepossible;
}
x2=0; y2=0;
}
if (xyok==0){
//check if horse can slide along a wall
if (yok==1){
x2=0;
goto horsemovepossible;
}
if (xok==1){
y2=0;
goto horsemovepossible;
}
x2=0; y2=0;
}
//OLD CODE: if (x2&&y2){x2=0; y2=0;} //can't move diagonally on a horse
}//diagonal movement
}//horse
horsemovepossible:
horse_finishdiagonalmove:
if (x2||y2){
if (((myobj->x+x2)==923)&&((myobj->y+y2)==872)){ //416 sacred quest
static txt *txttmp1;
if (!tplayer->GNPCflags[17]){
if (!tplayer->guardianstatuewait){
txttmp1=txtnew();
txtset(txttmp1,"\x022Thou art not upon a Sacred Quest!\x022\\\x022Passage denied!\x022");
i3=SFnew(923,872); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=923;
sf[i3].y=872-2;
sf[i3].wait=5;
sf[i3].more=187;
sf[i3].p=txttmp1;
tplayer->guardianstatuewait=8;
}
goto dontmove;
}
//sacred quest
x2=923;
if (y2==-1) y2=871;
if (y2==1) y2=873;
if (tplayer->craft==NULL){
//for (i4=7;i4>=0;i4--){
//if (tplayer->party[i4]){
//OBJremove(tplayer->party[i4]);
//OBJadd(x2,y2,tplayer->party[i4]);
//}
//}
partyadd(tplayer,x2,y2);
if (!tplayer->guardianstatuewait){
txttmp1=txtnew();
txtset(txttmp1,"\x022Passage granted!\x022");
i3=SFnew(923,872); //i3 points to new sf
sf[i3].type=3; //message to user
sf[i3].x=923;
sf[i3].y=872-2;
sf[i3].wait=5;
sf[i3].more=187;
sf[i3].p=txttmp1;
tplayer->guardianstatuewait=8;
}
}//craft
goto dontmove;
}//x,y
}//x2||y2
if (tplayer->pathfind){
tplayer->pathfind=0;
if ((x2==0)&&(y2==0)){
tplayer->pathfind=1;
//events which should stop a pathfind:
//i. switch party members
//ii. party member dies
//iii. path becomes blocked
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFright) x2=1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFleft) x2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFup) y2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFdown) y2=1;
if (tnpc->pathn>0) { //fix for pathfinding crash.
tnpc->pathn--;
}
if (tnpc->pathn==0) tplayer->pathfind=0;
}//x2==0,y2==0
}//pathfind
//BALLOON OVERRIDE!
if ((tplayer->party[0]->type&1023)==423){
//free flying with fan
if (tplayer->mobj && tplayer->mobj->type==212) {
goto selected_partymember_move;
}
x2=windx; y2=windy;
if ((tplayer->windx)||(tplayer->windy)){
x2=tplayer->windx; y2=tplayer->windy;
}
}
x3=tplayer->party[0]->x; y3=tplayer->party[0]->y;
if ((abs(x3-(myobj->x+x2))<=8)&&(abs(y3-(myobj->y+y2))<=8)){
if ((x2!=0)||(y2!=0)) goto selected_partymember_move;
}
} //selected party member
if (tnpc->order==1){ //try to move towards avatar
if (myobj2=tnpc->follow){
x2=0; y2=0;
x3=myobj->x-myobj2->x; y3=myobj->y-myobj2->y;
if (abs(x3)>abs(y3)) x4=abs(x3); else x4=abs(y3);//x4=distance from selected partymember
if (x4<=1) goto dontmove;
//get party order of npc
y5=1;
for (y4=0;y4<=7;y4++){ if (tplayer->party[y4]){
if (tplayer->party[y4]==myobj) goto follow_gotpartyorder;//<-GPF HERE (latest)
if (tnpc->follow!=tplayer->party[y4]){
y5++;
}
}}
follow_gotpartyorder:
if ((x4==2)&&(y5>=3)) goto dontmove;
if ((x4==3)&&(y5>=6)) goto dontmove;
/*
if (x4==3){
x4=rnd*2; if (x4) goto dontmove;
}
if (x4==2){
x4=rnd*3; if (x4) goto dontmove;
}
*/
//get path
/*
WPF_OBJECT=myobj; wpf_pathfind(tnpc->path,myobj->x,myobj->y,x2,y2,16,0,0);
if (WPF_RETURN==WPF_PATHFOUND){
if (WPF_PATHLENGTH){
tnpc->path_max=WPF_PATHLENGTH; tnpc->pathn=WPF_PATHLENGTH;
playerlist[tpl]->pathfind=1; //use pathfinding formula!
goto doneclmess;
}
playerlist[tpl]->pathfind=0; tnpc->path_max=0; tnpc->pathn=0;
}
}//party
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFright) x2=1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFleft) x2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFup) y2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFdown) y2=1;
tnpc->pathn--;
*/
if (tnpc->pathn){//use current path
follow_getpath:
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFright) x2=1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFleft) x2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFup) y2=-1;
if (tnpc->path[tnpc->path_max-tnpc->pathn]==PFdown) y2=1;
if (tnpc->pathn>0) { //fix for pathfinding crash.
tnpc->pathn--;
}
goto follow_gotpath;
}
z=abs(myobj2->x-myobj->x); z2=abs(myobj2->y-myobj->y); if (z2>z) z=z2;
z+=32; if (z>250) z=250;
WPF_OBJECT=myobj; wpf_pathfind(tnpc->path,myobj->x,myobj->y,myobj2->x,myobj2->y,z,0,1);//|1|PATHFIND THROUGH OWN PARTY+16
if (WPF_RETURN==WPF_PATHFOUND){
if (WPF_PATHLENGTH){
tnpc->path_max=WPF_PATHLENGTH; tnpc->pathn=WPF_PATHLENGTH;
goto follow_getpath;
}
}
//no path possible/(already at destination[can't be this value!])
tnpc->pathn=0; x2=0; y2=0;
tnpc->wait_walk+=0.5f;
goto donemove;
follow_gotpath:
//avoid hazards
z=abs(myobj2->x-myobj->x); z2=abs(myobj2->y-myobj->y); if ((z<=5)&&(z2<=5)){
z=wpf_dangercheck(myobj->x,myobj->y,myobj); z2=wpf_dangercheck(myobj->x+x2,myobj->y+y2,myobj); if (z2>z){x2=0; y2=0;}
}//z&&z2
//integrate player move and partymember->follow move
selected_partymember_move:
x3=0;
//wait! diagonal?!?
if ((abs(x2)+abs(y2))>1){ if (tplayer->craft==NULL){
if ((bt[myobj->y+y2][myobj->x]&1024)+(bt[myobj->y][myobj->x+x2]&1024)==0) goto NPC_skip1;
}}
if (OBJmove2(myobj,myobj->x+x2,myobj->y+y2)==0) x3=1;
if (x3==0){ //failed!
if ((abs(x2)+abs(y2))>1){ //diagonal
//attempt single movement along a plane
if (OBJmove2(myobj,myobj->x,myobj->y+y2)==0) {x3=1; x2=0; goto slidemove;}
if (OBJmove2(myobj,myobj->x+x2,myobj->y)==0) {x3=1; y2=0; goto slidemove;}
}
}
slidemove:
if (x3){
//if (tnpc->horse){
if (tnpc->horse&&(tplayer->craft==NULL)){
//wear down horseshoes?
x4=rnd*10000; if (x4==0){
crt2=(creature*)tnpc->horse->more;
x4=(crt2->respawn_x>>6)&3; if (x4) x4--;
crt2->respawn_x&=(0xFFFF-(3<<6));
crt2->respawn_x+=(x4<<6);
}//x4==0
//NEW horse wait
//8fps-16fps
//food 0-3 *2 0
//shoe 0-3 *2 0-6
//race 0-7(15) 0-8
//total 200.25->0.0625
//(0.25-0.0625=0.1875)
//(0.1875/20=0.009375)
crt2=(creature*)tnpc->horse->more; //this should fix the "all horse speeds same bug" and random crashes caused by uninitialized crt2
f=0.125;
f2=((crt2->respawn_x>>4)&3)*3;//food(0-15)
f2+=(((crt2->respawn_x>>6)&3)*3);//horseshoes(0-15)
f2+=(crt2->respawn_x&15);//races won(0-8) ***note: if horse races won>7 wait becomes less than 0.0625!***
f2*=0.00260417f;//0.0625/24
f-=f2;
if (horse_movediagonal==1) f*=1.4142f;
if (horse_movediagonal!=2) tnpc->wait_walk+=f;
goto wait_override;
}//->horse;
if ((myobj->type&1023)==423){ //balloon
f=0.25f;
if ((abs(x2)+abs(y2))>1) f*=1.4142f; //diagonal!
tnpc->wait_walk+=f;
goto wait_override;
}
if ((myobj->type&1023)==412){ //boat
//take into account wind direction & sea direction
//x2 and y2 are relative direction
f=0.0625f;
if ((abs(x2)+abs(y2))>1) f*=1.4142f; //diagonal!
tnpc->wait_walk+=f;
//additional current wait?
goto wait_override;
}
f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
//f=(0.25f-0.0625f-f*0.125f); //pre Mar
f=(0.25f-0.0625f-f*0.125f);
f=f*0.875f;
if ((abs(x2)+abs(y2))>1) f*=1.4142f; //diagonal!
tnpc->wait_walk+=f;
//if (selected_partymember){
//f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
//tnpc->wait_walk+=(0.25f-0.0625f-f*0.125f);
//}else{
////tnpc->wait_walk+=(0.0625f+(rnd*0.125f));
//f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
//tnpc->wait_walk+=(0.25f-0.0625f-f*0.125f);
//}
wait_override:;
}//x3
if ((x3==0)&&(tplayer->craft==NULL)){
//NPC is blocked! try swap
myobj2=myobj; //temp fix
myobj3=OBJfindlast(myobj2->x+x2,myobj2->y+y2);
if (myobj3){
//swapping into the back of a horse
if ((myobj3->type&1023)==431){
if (myobj3->info&8){
myobj4=(object*)myobj3->more;
tnpc2=(npc*)myobj4->more;
if ((tnpc2->player!=tnpc->player)||(selected_partymember)){
//if (tnpc->horse){
if (tnpc->horse&&(tplayer->craft==NULL)){
//MessageBox(NULL,"horse 2 horse swap!","Ultima 6 Online",MB_OK);
//swap both "types"
//invert both horse directions
x2=myobj2->x; y2=myobj2->y; z2=myobj2->type>>11;
x3=myobj4->x; y3=myobj4->y; z3=myobj4->type>>11;
OBJmove_allow=TRUE;
OBJmove2(myobj2,x3,y3);
z=z3; x4=0; y4=0;
if (z==0) y4=-1;
if (z==1) x4=1;
if (z==2) y4=1;
if (z==3) x4=-1;
OBJmove2(myobj2,myobj2->x+x4,myobj2->y+y4);
OBJmove2(myobj2,myobj2->x-x4*2,myobj2->y-y4*2);
OBJmove2(myobj4,x2,y2);
z=z2; x4=0; y4=0;
if (z==0) y4=-1;
if (z==1) x4=1;
if (z==2) y4=1;
if (z==3) x4=-1;
OBJmove2(myobj4,myobj4->x+x4,myobj4->y+y4);
OBJmove2(myobj4,myobj4->x-x4*2,myobj4->y-y4*2);
OBJmove_allow=FALSE;
goto doneswap;
}else{
//S->H(back)
x3=myobj4->x; y3=myobj4->y;
x4=0; y4=0;
//check adjacent squares of horse's head for walkability
if (bt[y3-1][x3]&1024){//walkable
x4=x3; y4=y3-1;
}
if (bt[y3][x3+1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3+1; y4=y3;}
x5=rnd*2; if (x5){x4=x3+1; y4=y3;}
}
if (bt[y3+1][x3]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3; y4=y3+1;}
x5=rnd*2; if (x5){x4=x3; y4=y3+1;}
}
if (bt[y3][x3-1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3-1; y4=y3;}
x5=rnd*2; if (x5){x4=x3-1; y4=y3;}
}
if (x4||y4){
OBJmove_allow=TRUE;
OBJmove2(myobj2,myobj3->x,myobj3->y);
OBJmove2(myobj4,x4,y4);
OBJmove_allow=FALSE;
goto doneswap;
}
//if no adjacent square is available then move on top of the back of the horse
OBJmove_allow=TRUE;
OBJmove2(myobj2,myobj3->x,myobj3->y);
OBJmove_allow=FALSE;
goto doneswap;
}//->horse
}//not in same party or is leader
goto NPC_skip1;
}//&8
//swap with head of a horse
myobj4=myobj3;
tnpc2=(npc*)myobj4->more;
//if (((object*)(tnpc2->more))->x==0) goto NPC_skip1;//!
if ((tnpc2->player!=tnpc->player)||(selected_partymember)){
//if (tnpc->horse){
if (tnpc->horse&&(tplayer->craft==NULL)){
//swap both "types"
//invert both horse directions
x2=myobj2->x; y2=myobj2->y; z2=myobj2->type>>11;
x3=myobj4->x; y3=myobj4->y; z3=myobj4->type>>11;
OBJmove_allow=TRUE;
OBJmove2(myobj2,x3,y3);
z=z3; x4=0; y4=0;
if (z==0) y4=-1;
if (z==1) x4=1;
if (z==2) y4=1;
if (z==3) x4=-1;
OBJmove2(myobj2,myobj2->x-x4,myobj2->y-y4);
OBJmove2(myobj2,myobj2->x+x4,myobj2->y+y4);
OBJmove2(myobj4,x2,y2);
z=z2; x4=0; y4=0;
if (z==0) y4=-1;
if (z==1) x4=1;
if (z==2) y4=1;
if (z==3) x4=-1;
OBJmove2(myobj4,myobj4->x-x4,myobj4->y-y4);
OBJmove2(myobj4,myobj4->x+x4,myobj4->y+y4);
OBJmove_allow=FALSE;
goto doneswap;
}else{
//S->H(front)
x3=((object*)tnpc2->more)->x; y3=((object*)tnpc2->more)->y;
//if (x3==0) goto NPC_skip1;//!
x4=0; y4=0;
//check adjacent squares of horse's head for walkability
if (bt[y3-1][x3]&1024){//walkable
x4=x3; y4=y3-1;
}
if (bt[y3][x3+1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3+1; y4=y3;}
x5=rnd*2; if (x5){x4=x3+1; y4=y3;}
}
if (bt[y3+1][x3]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3; y4=y3+1;}
x5=rnd*2; if (x5){x4=x3; y4=y3+1;}
}
if (bt[y3][x3-1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3-1; y4=y3;}
x5=rnd*2; if (x5){x4=x3-1; y4=y3;}
}
if (x4||y4){
OBJmove_allow=TRUE;
OBJmove2(myobj2,myobj4->x,myobj4->y);
OBJmove2(myobj4,x3,y3); OBJmove2(myobj4,x4,y4);
OBJmove_allow=FALSE;
goto doneswap;
}
//if no adjacent square is available a regular swap will occur...
}//->horse
}//not in same party or is leader
}//431
if (myobj3->info&2){ //<-npc
tnpc2=(npc*)myobj3->more;
if (tnpc2->player){
if (tnpc2->player->craft) goto NPC_skip1;
}
if (tnpc2->converse==128) goto NPC_skip1; //pushmepullyou
if (tnpc2->converse==130) goto NPC_skip1; //smith
if (tnpc2->converse==187) goto NPC_skip1;
if (tnpc2->converse==188) goto NPC_skip1;
if (tnpc2->converse==189) goto NPC_skip1;
if ((tnpc2->player!=tnpc->player)||(selected_partymember)){
//if ((myobj2->type&1023)==354){ //mouse
if (myobj4=OBJfindlastall(myobj2->x,myobj2->y)){
if ((myobj4->type&1023)==213) goto NPC_skip1; //mousehole
}
if (myobj4=OBJfindlastall(myobj2->x,myobj2->y)){
if (myobj4=(object*)myobj4->prev){
if (((myobj4->type&1023)==310)&&(myobj4->type&1024)) goto NPC_skip1; //portcullis
}
}
if (myobj4=OBJfindlastall(myobj2->x+x2,myobj2->y+y2)){
if ((myobj4->type&1023)==213) goto NPC_skip1; //mousehole
}
if (myobj4=OBJfindlastall(myobj2->x+x2,myobj2->y+y2)){
if (myobj4=(object*)myobj4->prev){
if (((myobj4->type&1023)==310)&&(myobj4->type&1024)) goto NPC_skip1; //portcullis
}
}
x2=myobj2->x; y2=myobj2->y;
x3=myobj3->x; y3=myobj3->y;
//}//mouse
//swap with NPC
//myobj4=od[y3][x3];
//if ((myobj4->type&1023)!=163){
//tnpc2=(npc*)myobj3->more;
x4=1; //bedswap2
if (tnpc2->schedule){ if (tnpc2->schedule_i!=-1){ if (tnpc2->schedule[tnpc2->schedule_i].type==0x91){ x4=0;}}}
if (x4){
//if (tnpc->horse){//player is on a horse, however target is not! (or it would have already been checked)
if (tnpc->horse&&(tplayer->craft==NULL)){
//CHECKED: can't swap diagonally
z=myobj2->type>>11; x4=0; y4=0;
if (z==0) y4=-1;
if (z==1) x4=1;
if (z==2) y4=1;
if (z==3) x4=-1;
x2-=x4; y2-=y4;
OBJmove_allow=TRUE;
OBJmove2(myobj2,x3,y3);
OBJmove2(myobj3,x2,y2);
OBJmove_allow=FALSE;
goto doneswap;
}
OBJmove_allow=TRUE;
OBJmove2(myobj2,x3,y3);
OBJmove2(myobj3,x2,y2);
OBJmove_allow=FALSE;
doneswap:
if (selected_partymember) tnpc->wait_walk+=0.125f; else tnpc->wait_walk+=(rnd*1.0f);
//***************
if (horse_movediagonal==1) {horse_movediagonal=2; x2=horse_movediagonalx; y2=horse_movediagonaly; goto horse_finishdiagonalmove;}
//tnpc->pathn++; //failed to move
//error: other characters path has been altered
tnpc2->pathn=0;
goto NPC_skip1;
}//bedswap
}//not in party
}//<-npc
}//!=NULL
//blocked! by a door? ->use
if (selected_partymember==0){
myobj2=OBJfindlast(myobj->x+x2,myobj->y+y2);
if (myobj2!=NULL){
x2=myobj2->type&1023;
if ((x2>=297)&&(x2<=300)){
if ((myobj2->type>>10)<8){//check if locked!
if ((myobj2->type&1024)){//ignore the secondary door parts
x=myobj2->type>>10;
if (x&1) {myobj3=myobj2; myobj2=(object*)myobj2->more;} else {myobj3=(object*)myobj2->more;}
if (x<4){
x=x>>1;
x=x<<1;
x=x&2;
myobj2->type=x2+((x+4)*1024);
myobj3->type=x2+((x+5)*1024);
OBJcheckflags(myobj2->x,myobj2->y); OBJcheckflags(myobj3->x,myobj3->y);
}else{
x=x>>1;
x=x<<1;
x=x&2;
myobj2->type=x2+(x*1024);
myobj3->type=x2+((x+1)*1024);
OBJcheckflags(myobj2->x,myobj2->y); OBJcheckflags(myobj3->x,myobj3->y);
} //<4
x2=myobj2->x; y2=myobj2->y;
i3=SFnew(x2,y2);
//i3 points to new sf
sf[i3].type=4;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=1.0f; //NULL
sf[i3].more=1;
f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
tnpc->wait_walk+=(0.25f-0.0625f-f*0.125f);
tnpc->pathn++; //failed to move
goto donemove;
}
}
}
}
}//end (blocked by door)
tnpc->pathn=0; if (selected_partymember) tplayer->pathfind=0;
dontmove:
if (!selected_partymember) tnpc->wait_walk+=0.5f;
}//x3==0 (blocked)
if (horse_movediagonal==1) {horse_movediagonal=2; x2=horse_movediagonalx; y2=horse_movediagonaly; goto horse_finishdiagonalmove;}
}//tnpc->follow
goto donemove;
}//order==1 (follow)
}//wait_walk
if (tnpc->order==3){ //attack target, if target==NULL find target
if (tnpc->target==NULL){ //chk vlnk
if (tplayer->party[tplayer->selected_partymember]==myobj) tnpc->order=0; else tnpc->order=1;
tnpc->follow=tplayer->party[tplayer->selected_partymember]; goto skipnpcattack;
}
static unsigned char spikedhelm_attack;
static unsigned char spikedhelm_onlyattack;
static object *spikedhelm;
spikedhelm_attack=0;
spikedhelm_onlyattack=0;
if (spikedhelm=tnpc->helm){
if (spikedhelm->type==4){
if (tplayer->craft==NULL){
spikedhelm_attack=1;
}
}
}
myobj3=tnpc->wep_left; myobj4=tnpc->wep_right;
if (myobj3&&myobj4){ //object in both hands
//can't attack with equiped items!
if ((spikedhelm_attack==0)&&(obji[sprlnk[myobj3->type&1023]].v1==0)&&(obji[sprlnk[myobj4->type&1023]].v1==0)) goto skipnpcattack;
if (spikedhelm_attack){
if ((obji[sprlnk[myobj3->type&1023]].v1==0)&&(obji[sprlnk[myobj4->type&1023]].v1==0)) spikedhelm_onlyattack=1;
}
}
static unsigned char attack_item; attack_item=FALSE;
myobj2=tnpc->target; if (tnpc->target->info&4) crt=(creature*)myobj2->more; else attack_item=TRUE;
if (tnpc->wait_disable) goto skipnpcattack; //can't move or attack!
if (tnpc->wait_attack){
if (selected_partymember) goto skipnpcattack; //movement is manual!
if (tnpc->wait_walk) goto skipnpcattack; //can't move closer anyway!
//i. check minimum range of all equipped weapons
x2=65536; //distance required to attack (-1=can't attack!)
for (x3=0;x3<=1;x3++){
if (x3==0) myobj3=tnpc->wep_right; //right hand weapon
if (x3==1) myobj3=tnpc->wep_left; //left hand weapon
if (myobj3){
if (obji[sprlnk[myobj3->type&1023]].v1) x4=1; else x4=65536;
x5=myobj3->type&1023;
if (x5==OBJ_BOW) x4=8;
if (x5==OBJ_MAGIC_BOW) x4=8;
if (x5==OBJ_TRIPLE_CROSSBOW) x4=8;
if (x5==OBJ_SLING) x4=4;
if (x5==OBJ_LIGHTNING_WAND) x4=8;
if (x5==OBJ_FIRE_WAND) x4=8;
if (x5==OBJ_CROSSBOW) x4=8;
if (x5==OBJ_BOOMERANG) x4=8;
if (x5==OBJ_FLASK_OF_OIL) x4=8;
if (x5==OBJ_DAGGER) x4=8;
if (x5==OBJ_THROWING_AXE) x4=8;
if (x5==OBJ_SPEAR) x4=8;
if (x5==OBJ_HALBERD) x4=2;//halberd
if (x5==OBJ_MORNING_STAR) x4=2;//morning star
if (obji[sprlnk[myobj3->type&1023]].flags&16){
x2=x4; goto npcattack2hnd;
}
if (x4<x2) x2=x4;
}else{
//bare hands attack possible, close in on target
x2=1;
}
}//x3
npcattack2hnd:
if (spikedhelm_attack) x2=1;//set minimum range required to use weapon
if (tplayer->craft) x2=8;
//ii. if distance 2 target is more than minimum range close in on target
x=abs(myobj->x-myobj2->x); y=abs(myobj->y-myobj2->y);
if (x>y) x4=x; else x4=y; //x4=distance to target
if ((x4>x2)&&(x2!=65536)) goto npcattackclose;
goto skipnpcattack; //doesn't need to move and can't attack!
}//tnpc->wait_attack
//if (crt->hp<=0){
//tnpc->order=1; tnpc->follow=tplayer->party[tplayer->selected_partymember]; goto skipnpcattack;
//}
//check distance?
x=abs(myobj->x-myobj2->x);
y=abs(myobj->y-myobj2->y);
if (x>y) x2=x; else x2=y; //x2=distance to target
//if ((x<=1)&&(y<=1)) x2=1; //close
//add l&r hand dam
x=0; x9=0;
static unsigned char miss;
static unsigned char wep_dt[2];
wep_dt[0]=0; wep_dt[1]=0;
//RESERVED! x,x9
miss=0;
static unsigned char triplecrossbow_shot;
triplecrossbow_shot=0;
static unsigned short triplecrossbow_shot_x2;
static unsigned short triplecrossbow_shot_y2;
static unsigned short triplecrossbow_shot_x3;
static unsigned short triplecrossbow_shot_y3;
static unsigned short npcattackweptype;
if (spikedhelm_onlyattack){
if (x2>1) goto attacknotpossible;//close in
spikedhelm_attack=0; spikedhelm_onlyattack=0;//clear set variables
myobj3=NULL;
i3=1;
wep_dt[1]=1;
x=4;
if (tplayer->craft==NULL) OBJdir(myobj,myobj2->x,myobj2->y);
//add wait
f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
f=2.0f-(f*0.25f);
tnpc->wait_attack+=f;
//add sfx
i4=SFnew(myobj2->x,myobj2->y);
sf[i4].type=1; //attack
sf[i4].x=myobj2->x;
sf[i4].y=myobj2->y;
sf[i4].x2=0;
sf[i4].wait=0.125f; //NULL
sf[i4].more=1;
goto spikedhelm_entrypoint;
}else{
if (spikedhelm_attack){
if (x2>1) spikedhelm_attack=0;//not within range
}
}
for (x3=0;x3<=1;x3++){
npcattackweptype=0;
if (x3==0) myobj3=tnpc->wep_right; //right hand weapon
if (x3==1) myobj3=tnpc->wep_left; //left hand weapon
if (tplayer->craft){ //ship cannons
myobj3=NULL;
if (x3==0){ if (x2<=8){
//do a MAJOR jump into the attack section!!!
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)) goto skip_hth1;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=17;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=30;
goto skip_hth2;
}}
goto skip_hth1;
}
if (myobj3){
npcattackweptype=myobj3->type&1023;
if (x3) wep_dt[0]=obji[sprlnk[myobj3->type&1023]].v5; else wep_dt[1]=obji[sprlnk[myobj3->type&1023]].v5;
//special case(s)
if (x2<=8){ //long range
if ((myobj3->type&1023)==47){ //halberd
if (x2==2){//only check if range 2
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//blocked! (will be processed as out of range)
}else{
x7=myobj2->x;
if (myobj->x>(myobj2->x+1)) x7++;
if (myobj->x<(myobj2->x-1)) x7--;
y7=myobj2->y;
if (myobj->y>(myobj2->y+1)) y7++;
if (myobj->y<(myobj2->y-1)) y7--;
if (myobj2->x!=x7){ //discrepancy x
x5=x7; y5=myobj2->y; x6=0;
if (myobj9=OBJfindlast(x5,y5)){
if (myobj9->info&8) myobj9=(object*)myobj9->more;
if (myobj9->info&(2+4)) x6=1; //something living is in the way
}//myobj9
if (bt[y5][x5]&1024) x6=1; //character can walk there
if (x6==0) goto halberd_failedcheck;
}
if (myobj2->y!=y7){ //discrepancy y
x5=myobj2->x; y5=y7; x6=0;
if (myobj9=OBJfindlast(x5,y5)){
if (myobj9->info&8) myobj9=(object*)myobj9->more;
if (myobj9->info&(2+4)) x6=1; //something living is in the way
}//myobj9
if (bt[y5][x5]&1024) x6=1; //character can walk there
if (x6==0) goto halberd_failedcheck;
}
x7=myobj2->x;
if (myobj->x>myobj2->x) x7++;
if (myobj->x<myobj2->x) x7--;
y7=myobj2->y;
if (myobj->y>myobj2->y) y7++;
if (myobj->y<myobj2->y) y7--;
if ((x7!=myobj2->x)&&(y7!=myobj2->y)){
x5=x7; y5=y7; x6=0;
if (myobj9=OBJfindlast(x5,y5)){
if (myobj9->info&8) myobj9=(object*)myobj9->more;
if (myobj9->info&(2+4)) x6=1; //something living is in the way
}//myobj9
if (bt[y5][x5]&1024) x6=1; //character can walk there
if (x6==0) goto halberd_failedcheck;
}
goto hth_norangecheck;
halberd_failedcheck:;
}//OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)
}//==2
}//halberd
if ((myobj3->type&1023)==40){ //morning star
if (x2==2){//only check if range 2
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//blocked! (will be processed as out of range)
}else{
x7=myobj2->x;
if (myobj->x>(myobj2->x+1)) x7++;
if (myobj->x<(myobj2->x-1)) x7--;
y7=myobj2->y;
if (myobj->y>(myobj2->y+1)) y7++;
if (myobj->y<(myobj2->y-1)) y7--;
if (myobj2->x!=x7){ //discrepancy x
x5=x7; y5=myobj2->y; x6=0;
if (myobj9=OBJfindlast(x5,y5)){
if (myobj9->info&8) myobj9=(object*)myobj9->more;
if (myobj9->info&(2+4)) x6=1; //something living is in the way
}//myobj9
if (bt[y5][x5]&1024) x6=1; //character can walk there
if (x6==0) goto morningstar_failedcheck;
}
if (myobj2->y!=y7){ //discrepancy y
x5=myobj2->x; y5=y7; x6=0;
if (myobj9=OBJfindlast(x5,y5)){
if (myobj9->info&8) myobj9=(object*)myobj9->more;
if (myobj9->info&(2+4)) x6=1; //something living is in the way
}//myobj9
if (bt[y5][x5]&1024) x6=1; //character can walk there
if (x6==0) goto morningstar_failedcheck;
}
x7=myobj2->x;
if (myobj->x>myobj2->x) x7++;
if (myobj->x<myobj2->x) x7--;
y7=myobj2->y;
if (myobj->y>myobj2->y) y7++;
if (myobj->y<myobj2->y) y7--;
if ((x7!=myobj2->x)&&(y7!=myobj2->y)){
x5=x7; y5=y7; x6=0;
if (myobj9=OBJfindlast(x5,y5)){
if (myobj9->info&8) myobj9=(object*)myobj9->more;
if (myobj9->info&(2+4)) x6=1; //something living is in the way
}//myobj9
if (bt[y5][x5]&1024) x6=1; //character can walk there
if (x6==0) goto morningstar_failedcheck;
}
goto hth_norangecheck;
morningstar_failedcheck:;
}//OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)
}//==2
}//morning star
if ((myobj3->type&1023)==41){ //bow
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==55){ //arrow
OBJlist_list[y6]->more2--;
if (OBJlist_list[y6]->more2==0) OBJremove(OBJlist_list[y6]);
tnpc->upflags|=32;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=2; //arrow
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x3) wep_dt[0]=3; else wep_dt[1]=3;
goto skip_hth2;
}//->type==55
}//y6
goto skipnpcattack;
}//OBJcheckbolt
goto skip_hth2;
}//bow
if ((myobj3->type&1023)==54){ //magic bow
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==55){ //arrow
OBJlist_list[y6]->more2--;
if (OBJlist_list[y6]->more2==0) OBJremove(OBJlist_list[y6]);
tnpc->upflags|=32;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=2; //arrow
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x3) wep_dt[0]=3; else wep_dt[1]=3;
goto skip_hth2;
}//->type==55
}//y6
goto skipnpcattack;
}//OBJcheckbolt
goto skip_hth2;
}//magic bow
if ((myobj3->type&1023)==50){ //triple crossbow
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==56){ //bolt
if (OBJlist_list[y6]->more2>=3){ //3 bolts
OBJlist_list[y6]->more2-=3;
if (OBJlist_list[y6]->more2==0) OBJremove(OBJlist_list[y6]);
tnpc->upflags|=32;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=6; //bolt
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
triplecrossbow_shot=2;
//2 more shots
x6=myobj2->x; y6=myobj2->y; x7=myobj2->x; y7=myobj2->y;
if ((x6>myobj->x)&&(y6>myobj->y)){y6--; x7--; goto crossbow0;}
if ((x6>myobj->x)&&(y6<myobj->y)){x6--; y7++; goto crossbow0;}
if ((x6<myobj->x)&&(y6<myobj->y)){y6++; x7++; goto crossbow0;}
if ((x6<myobj->x)&&(y6>myobj->y)){x6++; y7--; goto crossbow0;}
if (x6>myobj->x){y6--; y7++; goto crossbow0;}
if (x6<myobj->x){y6++; y7--; goto crossbow0;}
if (y6<myobj->y){x6--; x7++; goto crossbow0;}
if (y6>myobj->y){x6++; x7--; goto crossbow0;}
crossbow0:
triplecrossbow_shot_x2=x6; triplecrossbow_shot_y2=y6;
triplecrossbow_shot_x3=x7; triplecrossbow_shot_y3=y7;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=6; //bolt
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=x6;
sf[i3].y2=y6;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=6; //bolt
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=x7;
sf[i3].y2=y7;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x3) wep_dt[0]=3; else wep_dt[1]=3;
goto skip_hth2;
}//3 arrows
}//->type==56
}//y6
goto skipnpcattack;
}//OBJcheckbolt
goto skip_hth2;
}//triple crossbow
if ((myobj3->type&1023)==33){ //sling
if (x2<=4){ //short range
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=13; //arrow
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
}//OBJcheckbolt
}//short range
goto skip_hth2;
}//sling
if ((myobj3->type&1023)==79){ //lightning wand
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
//u6ob
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=5; //wand
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x3) wep_dt[0]=5; else wep_dt[1]=5;
//destroy item???
x8=myobj3->more2;
if (x8==0) x8=256;
x8--;
myobj3->more2=x8;
if (x8==0){
//if (x3==0) {OBJrelease(tnpc->wep_right); tnpc->wep_right=NULL;} //right hand weapon
//if (x3==1) {OBJrelease(tnpc->wep_left); tnpc->wep_left=NULL;} //left hand weapon
if (x3==0) tnpc->wep_right=NULL; //right hand weapon
if (x3==1) tnpc->wep_left=NULL; //left hand weapon
tnpc->upflags|=64;
}
}
goto skip_hth2;
}
if ((myobj3->type&1023)==80){ //fire wand
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
//u6ob
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=8; //wand
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x3) wep_dt[0]=5; else wep_dt[1]=5;
//destroy item???
x8=myobj3->more2;
if (x8==0) x8=256;
x8--;
myobj3->more2=x8;
if (x8==0){
//if (x3==0) {OBJrelease(tnpc->wep_right); tnpc->wep_right=NULL;} //right hand weapon
//if (x3==1) {OBJrelease(tnpc->wep_left); tnpc->wep_left=NULL;} //left hand weapon
if (x3==0) tnpc->wep_right=NULL; //right hand weapon
if (x3==1) tnpc->wep_left=NULL; //left hand weapon
tnpc->upflags|=64;
}
}
goto skip_hth2;
}
if ((myobj3->type&1023)==42){ //crossbow
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==56){ //bolt
OBJlist_list[y6]->more2--;
if (OBJlist_list[y6]->more2==0) OBJremove(OBJlist_list[y6]);
tnpc->upflags|=32;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=6; //crossbow
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x3) wep_dt[0]=3; else wep_dt[1]=3;
goto skip_hth2;
}//==56
}//y6
goto skipnpcattack;
}
goto skip_hth2;
}
if ((myobj3->type&1023)==49){ //boomerang
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
//u6ob
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=7; //boomerang
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=2;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
//drop it by accident?
x8=rnd*(tnpc->d+1);
if (x8==0){
if (x3==0) tnpc->wep_right=NULL; //right hand weapon
if (x3==1) tnpc->wep_left=NULL; //left hand weapon
//insert myobj3
myobj3->prev=myobj2->prev; myobj3->x=myobj2->x; myobj3->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj3;
}else{
od[myobj2->y][myobj2->x]=myobj3;
}
myobj2->prev=myobj3;
myobj3->next=myobj2;
myobj3->info|=112; //set flags as temp OBJ
AUTOPICKUPadd(myobj,myobj3);
tnpc->upflags|=64;
//equip new one
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==49){//boomerang
OBJremove(OBJlist_list[y6]);
if (x3==0) tnpc->wep_right=OBJlist_list[y6]; //right hand weapon
if (x3==1) tnpc->wep_left=OBJlist_list[y6]; //left hand weapon
tnpc->upflags|=32;
goto boomerang_new;
}}
boomerang_new:;
}
}
goto skip_hth2;
}//boomerang
if ((myobj3->type&1023)==83){ //oil flask
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//it would hit the wall (ignore)
}else{
//u6ob
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=9; //GENERIC throw object
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=83;
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
//toss it!
//x9=rnd*32;
//if (x9==0){
if (x3==0) tnpc->wep_right=NULL; //right hand weapon
if (x3==1) tnpc->wep_left=NULL; //left hand weapon
myobj9=OBJnew();
myobj9->type=317; //fire
//insert object9
myobj9->prev=myobj2->prev; myobj9->x=myobj2->x; myobj9->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj9;
}else{
od[myobj2->y][myobj2->x]=myobj9;
}
myobj2->prev=myobj9;
myobj9->next=myobj2;
myobj9->more2=tnpc->player->id;
myobj9->info&=(0xFFFF-112); myobj9->info|=(2<<4);
myobj9->x=myobj2->x; myobj9->y=myobj2->y;
OBJcheckflags(myobj9->x,myobj9->y);
//equip new one?
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==83){ //flask
OBJlist_list[y6]->more2--;
if (OBJlist_list[y6]->more2==0){
OBJremove(OBJlist_list[y6]);
}
myobj9=OBJnew();
myobj9->type=83;
myobj9->more2=1;
if (x3==0) tnpc->wep_right=myobj9; //right hand weapon
if (x3==1) tnpc->wep_left=myobj9; //left hand weapon
tnpc->upflags|=32;
goto oilflask_new;
}}
oilflask_new:
tnpc->upflags|=64;
//32 inventory, bag icon
//64 equipped items
//}
}
goto skip_hth2;
}
if ((myobj3->type&1023)==38){ //dagger
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//blocked!
}else{
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x2>1){ //throw
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=10; //dagger
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
if (x3==0) tnpc->wep_right=NULL; //right hand weapon
if (x3==1) tnpc->wep_left=NULL; //left hand weapon
//insert object3
myobj3->prev=myobj2->prev; myobj3->x=myobj2->x; myobj3->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj3;
}else{
od[myobj2->y][myobj2->x]=myobj3;
}
myobj2->prev=myobj3;
myobj3->next=myobj2;
myobj3->info|=112; //set flags as temp OBJ
AUTOPICKUPadd(myobj,myobj3);
tnpc->upflags|=64;
//equip new one?
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==38){ //dagger
OBJremove(OBJlist_list[y6]);
if (x3==0) tnpc->wep_right=OBJlist_list[y6]; //right hand weapon
if (x3==1) tnpc->wep_left=OBJlist_list[y6]; //left hand weapon
tnpc->upflags|=32;
goto dagger_new;
}}
dagger_new:;
}else{goto skip_hthx;} //throw
}
goto skip_hth2;
}
if ((myobj3->type&1023)==37){ //throwing axe
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//blocked!
}else{
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x2>1){ //throw
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=11; //throwing axe
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
if (x3==0) tnpc->wep_right=NULL; //right hand weapon
if (x3==1) tnpc->wep_left=NULL; //left hand weapon
//insert object3
myobj3->prev=myobj2->prev; myobj3->x=myobj2->x; myobj3->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj3;
}else{
od[myobj2->y][myobj2->x]=myobj3;
}
myobj2->prev=myobj3;
myobj3->next=myobj2;
myobj3->info|=112; //set flags as temp OBJ
AUTOPICKUPadd(myobj,myobj3);
tnpc->upflags|=64;
//equip new one?
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==37){ //throwing axe
OBJremove(OBJlist_list[y6]);
if (x3==0) tnpc->wep_right=OBJlist_list[y6]; //right hand weapon
if (x3==1) tnpc->wep_left=OBJlist_list[y6]; //left hand weapon
tnpc->upflags|=32;
goto axe_new;
}}
axe_new:;
}else{goto skip_hthx;} //throw
}
goto skip_hth2;
}
if ((myobj3->type&1023)==36){ //spear
if (OBJcheckbolt(myobj->x,myobj->y,myobj2->x,myobj2->y)){
//blocked!
}else{
x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (x2>1){ //throw
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=12; //spear
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
if (x3==0) tnpc->wep_right=NULL; //right hand weapon
if (x3==1) tnpc->wep_left=NULL; //left hand weapon
//insert object3
myobj3->prev=myobj2->prev; myobj3->x=myobj2->x; myobj3->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj3;
}else{
od[myobj2->y][myobj2->x]=myobj3;
}
myobj2->prev=myobj3;
myobj3->next=myobj2;
myobj3->info|=112; //set flags as temp OBJ
AUTOPICKUPadd(myobj,myobj3);
tnpc->upflags|=64;
//equip new one?
x5=OBJlist((object*)tnpc->items->more); //x5=last object number
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==36){ //spear
OBJremove(OBJlist_list[y6]);
if (x3==0) tnpc->wep_right=OBJlist_list[y6]; //right hand weapon
if (x3==1) tnpc->wep_left=OBJlist_list[y6]; //left hand weapon
tnpc->upflags|=32;
goto spear_new;
}}
spear_new:;
}else{goto skip_hthx;} //throw
}
goto skip_hth2;
}
goto skip_hthx; //not long range!
skip_hth2: //skipped other weapon types, projectile weapon
//miss?
if (x){ //can do damage
x7=rnd*(tnpc->d+1);
x8=rnd*16; /* this should be dependant on target being attacked I think and with some weapons it should be easier to hit (ranged weapons need higher dex and heavy melee weapons lower) */
if (x7<x8) {
x=0; miss=1;
//if bow, magic bow, or crossbow, drop an arrow at the destination 50% of the time
if ((npcattackweptype==41)||(npcattackweptype==54)||(npcattackweptype==42)||(npcattackweptype==50)){
x7=rnd*2; if (x7){ //50% chance
myobj9=OBJnew();
AUTOPICKUPadd(myobj,myobj9);
myobj9->type=55; //arrow
if ((npcattackweptype==42)||(npcattackweptype==50)) myobj9->type=56; //bolt
myobj9->more2=1;
//insert object9
myobj9->prev=myobj2->prev; myobj9->x=myobj2->x; myobj9->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj9;
}else{
od[myobj2->y][myobj2->x]=myobj9;
}
myobj2->prev=myobj9;
myobj9->next=myobj2;
myobj9->info|=112; //set flags as temp OBJ
myobj9->x=myobj2->x; myobj9->y=myobj2->y;
OBJcheckflags(myobj9->x,myobj9->y);
}//x7
}//npcattackweptype
if (triplecrossbow_shot){
if (tnpc->wait_attack||tnpc->wait_disable) goto skipnpcattack;
f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
tnpc->wait_attack+=2.0-(f*0.25f);
goto triplecrossbow_miss;
}
}//missed!
}//x
goto skip_hth1;
} //x2<=8 (long range)
skip_hthx: //not a long range weapon
if (x2<=1){
hth_norangecheck:
if (x==0) x+=obji[sprlnk[myobj3->type&1023]].v1+ENHANCEget_attack(myobj3);
if (myobj3->type==48) x=1023;
}//x2<=1
}//myobj3
if ((x3==1)&&(x==0)&&(x9==0)&&(x2<=1)){ //attack with bare hands!
wep_dt[1]=1;
x=1;
}
skip_hth1:;
if (x3==0) {x9=x; x=0;}
}//x3
if (x||x9){
//attack possible
//ERROR! it fires the arrow but can't actually attack because attack waiting in ON!
//this could cause hell for NPC!
//
if (tplayer->craft==NULL) OBJdir(myobj,myobj2->x,myobj2->y);
f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
f=2.0f-(f*0.25f);
if (spikedhelm_attack){
if (x&&x9) f*=1.25f; else f*=1.125f;
}else{
if (x&&x9) f*=1.125f;
}
tnpc->wait_attack+=f;
i4=SFnew(myobj2->x,myobj2->y);
sf[i4].type=1; //attack
sf[i4].x=myobj2->x;
sf[i4].y=myobj2->y;
sf[i4].x2=0;
sf[i4].wait=0.125f; //NULL
sf[i4].more=1;
for (i3=0;i3<=1;i3++){
if (i3) x=x9;
if (x){
if (i3==0) myobj3=tnpc->wep_left; else myobj3=tnpc->wep_right; //NOTE: this value may not point to an actual weapon!
triplecrossbow_refire:
spikedhelm_entrypoint:
if (attack_item){
if (myobj2->type==53){
if (myobj3){ if (myobj3->type==48){ //smash glass sword!
if (i3==0) tnpc->wep_left=NULL; else tnpc->wep_right=NULL;
tnpc->upflags|=64; }}
//web strength
x2=rnd*(x+1); //attack strength
x3=rnd*(128+1); //web strength
if (x2>x3){
OBJsave(myobj2->x,myobj2->y);
VLNKremove(myobj2);
OBJremove(myobj2);
myobj2=NULL; goto attackdone;
}//x2>x3
}//53
if ((myobj2->type&1023)==98){ //chest
x2=0;
if (myobj2->type<=(98+1024)) x2=1; //closed/opened
if (myobj2->type==(98+2048)) x2=1; //locked
if (x2){
if (myobj3){ if (myobj3->type==48){ //smash glass sword!
if (i3==0) tnpc->wep_left=NULL; else tnpc->wep_right=NULL;
tnpc->upflags|=64; }}
x2=rnd*(x+1); //attack
x3=rnd*(256+1); //chest
if (x2>x3){
x3=myobj2->x; y3=myobj2->y;
OBJsave(x3,y3);
VLNKremove(myobj2);
//VLNKsremove(myobj2);
OBJremove(myobj2);
//extract items
myobj=myobj2;
extractobj5:
myobj2=(object*)myobj->more;
if (myobj2!=NULL) {OBJremove(myobj2); myobj2->info|=112; OBJadd(x3,y3,myobj2); goto extractobj5;}
myobj2=NULL; goto attackdone;
}//x2
}//x2>x3
}//98
goto attack_item_skip2;
}
if (myobj3){
if (myobj3->type==OBJ_FIRE_WAND){//fire wand
x2=myobj2->type&1023;
if (x2==411) x=0;//dragon
if (x2==369) x=0;//drake
if (x2==352) x=0;//ghost
if (x2==374) x=0;//hydra
if (x2==369) x=0;//drake
if (x2==368) x=0;//skeleton
if (x2==373) x=0;//wisp
if (x2==367) x=0;//daemon
//double damage?
if (x2==364) x*=2; //acid slug
if (x2==357) x*=2; //corpser
if (x2==347) x*=2; //reaper
if (x2==360) x*=2; //rot worms
if (x2==375) x*=2; //slime
if (x2==365) x*=2; //tangle vine
}
}
//slime divide!
if ((myobj2->type&1023)==OBJ_SLIME){
static unsigned long slimex,slimey;
if ((myobj2->info&(15<<9))==0) goto slimedivide_failed;
//test surrounding squares
slimex=myobj2->x+1; slimey=myobj2->y;
if ((od[slimey][slimex]==NULL)&&((bt[slimey][slimex]>>10)&1)) goto slimedivide;
slimex=myobj2->x-1; slimey=myobj2->y;
if ((od[slimey][slimex]==NULL)&&((bt[slimey][slimex]>>10)&1)) goto slimedivide;
slimex=myobj2->x; slimey=myobj2->y+1;
if ((od[slimey][slimex]==NULL)&&((bt[slimey][slimex]>>10)&1)) goto slimedivide;
slimex=myobj2->x; slimey=myobj2->y-1;
if ((od[slimey][slimex]==NULL)&&((bt[slimey][slimex]>>10)&1)) goto slimedivide;
goto slimedivide_failed;
slimedivide:
myobj3=OBJnew();
myobj3->type=375;
myobj3->more=malloc(sizeof(creature));
ZeroMemory(myobj3->more,sizeof(creature));
crt3=(creature*)myobj3->more;
crt3->crt_struct=TRUE;
crt3->hp=(obji[sprlnk[myobj3->type&1023]].v8>>8)*4;
crt3->mp=0;
crt3->al=1;
crt3->respawn_x=1024; //seconds till spawned crt will disappear
myobj9=OBJnew(); myobj9->type=188; crt3->items=myobj9; //(not included)bag
myobj3->info|=4; //<-crt
OBJmove2(myobj3,slimex,slimey);
x2=(myobj2->info>>9)&15; x2--;
myobj2->info&=(0xFFFF-(15<<9));
myobj2->info|=(x2<<9);
myobj3->info|=(x2<<9);
slimedivide_failed:;
}
f=x; //default (unclassified) bonus
//OLD VALUES
//if (wep_dt[i3]==1) f=(float)x/32.0f*(float)tnpc->s; //100% STR
//if (wep_dt[i3]==2) f=(float)x/32.0f*(((float)tnpc->s/2.0f)+((float)tnpc->d/2.0f)); //50% STR + 50% DEX
//if (wep_dt[i3]==3) f=(float)x/32.0f*((float)tnpc->d*2.0f); //200% DEX (bows, crossbows)
if (wep_dt[i3]==1) f=(float)x/32.0f*((float)tnpc->s+(float)tnpc->d*0.25f);//STR*100%+DEX*25%
if (wep_dt[i3]==2) f=(float)x/32.0f*((float)tnpc->d*0.75f+(float)tnpc->s*0.25f);//DEX*75%+STR*25%
if (wep_dt[i3]==3) f=(float)x/32.0f*((float)tnpc->d*1.75f);//DEX*175%
if (wep_dt[i3]==4){
//DEX*100% or STR*100%, whichever is lower
if (tnpc->s<=tnpc->d){
f=(float)x/32.0f*( (float)tnpc->s + ((float)tnpc->d-(float)tnpc->s)*0.25f );
}else{
f=(float)x/32.0f*( (float)tnpc->d + ((float)tnpc->s-(float)tnpc->d)*0.25f );
}
}
if (wep_dt[i3]==5) f=(float)x/32.0f*((float)tnpc->i*0.125f+8);//INT*12.5% wands are magical weapons, so they should have some base damage bonus in u6 they were quite good */
x2=rnd*((float)(x*2)+f+1.0f)-(float)x; //weapon damage
if (x2>x) x2=x;
if (tplayer->craft) x2=rnd*31.0f; //cannons (can't graze target!)
x2-=(int)(rnd*((obji[sprlnk[myobj2->type&1023]].v7>>8)+1+1+getequiparmourvalue((object*)crt->items->more))); //enemy arm +1
if (x2<0) x2=0;
if (tplayer->craft) goto nododge;
if (wep_dt[i3]==3) goto nododge;
if (int(rnd*32)<=int(rnd*((obji[sprlnk[myobj2->type&1023]].v6>>8)+1))){
x2=0; //enemy dodged the attack!
}
nododge:
sf[i4].x2+=x2;
if (sf[i4].x2==0) sf[i4].type=16; else sf[i4].type=1; //change attack to a miss type?
if (x2){
if (myobj3){ if (myobj3->type==48){ //smash glass sword!
if (i3==0) tnpc->wep_left=NULL; else tnpc->wep_right=NULL;
tnpc->upflags|=64; }}
}
//x7=rnd*32; //0-127
//x8=rnd*(tnpc->d+1);
//if (x7>x8){ //couldn't dodge the attack!
spellattcrt0:
if (myobj){ //valid source of attack exists
if (crt->al==0){ //passive
if ( ((myobj2->type&1023)!=430) || ((crt->flags&128)==0) ){//horse exception
crt->al=3; //passive turned aggressive
crt->target=myobj;
VLNKsremove(myobj2); //remove prev vlnk
VLNKnew(myobj2,crt->target,(unsigned long)&crt->target); //add vlnk
}//horse exception
}
if (crt->al==4){ //defend itself!
crt->target=myobj;
VLNKsremove(myobj2); //remove prev vlnk
VLNKnew(myobj2,crt->target,(unsigned long)&crt->target); //add vlnk
}
}
if (crt->flags&4){ if (x2){ //wake creature if asleep!
crt->wait=0;
if (crt->flags&8) crt->flags-=8; //unparalyze //1=poison, 2=invisible, 4=asleep, 8=paralyzed
if (crt->flags&4) crt->flags-=4; //awaken //1=poison, 2=invisible, 4=asleep, 8=paralyzed
}}
crt->hp-=x2; if (crt->hp<0) crt->hp=0;
if ((myobj2->type&1023)==366) crt->hp=32767; //invincible tanglevine tendril!
if ((myobj2->type&1023)==430) if (crt->flags&128) crt->hp=32767;//invincible horse
if (crt->hp<=0){
if (tnpc){ //valid tnpc
tnpc->player->midi=255; //invalid number!
if (tnpc->player->craft==NULL){ //*2004 TEMP
if (myobj2->type==355) {
myobj4=OBJnew();
myobj4->type=343; //insects
myobj4->more=malloc(sizeof(creature));
ZeroMemory(myobj4->more,sizeof(creature));
crt3=(creature*)myobj4->more;
crt3->crt_struct=TRUE;
crt3->hp=(obji[sprlnk[myobj4->type&1023]].v8>>8)*4;
crt3->mp=rnd*9;
crt3->al=1;
crt3->respawn_x=1024; //seconds till spawned crt will disappear
myobj9=OBJnew(); myobj9->type=188; crt3->items=myobj9; //(not included)bag
myobj4->info|=4; //<-crt
OBJadd(myobj2->x,myobj2->y,myobj4);
}
myobj4=NULL;
if (mover_blood[myobj2->type&1023]){
myobj4=OBJnew();
myobj4->type=338+(int(rnd*3)*1024);
myobj4->info|=112;
}
if (mover_body[myobj2->type&1023]){
//if it's a cyclops or a winged garg, check surrounding squares for practicality
//of a body drop
if ((mover_body[myobj2->type&1023]==(340+1024*3))||(mover_body[myobj2->type&1023]==(341+1024*3))){
//RULE 1: all basetiles must have an object walkable flag
if ((btflags[bt[myobj2->y][myobj2->x]&1023]&1)==0) goto nospaceforbody;
if ((btflags[bt[myobj2->y-1][myobj2->x]&1023]&1)==0) goto nospaceforbody;
if ((btflags[bt[myobj2->y][myobj2->x-1]&1023]&1)==0) goto nospaceforbody;
if ((btflags[bt[myobj2->y-1][myobj2->x-1]&1023]&1)==0) goto nospaceforbody;
//RULE 2: only 1 object may exist on the square at the time of the drop
//FACT: the object is a 4 part mover, there WILL be a first object on each square
if (od[myobj2->y][myobj2->x]->next) goto nospaceforbody;
if (od[myobj2->y-1][myobj2->x]->next) goto nospaceforbody;
if (od[myobj2->y][myobj2->x-1]->next) goto nospaceforbody;
if (od[myobj2->y-1][myobj2->x-1]->next) goto nospaceforbody;
}
if (mover_body[myobj2->type&1023]==(134+1024*1)){//carcass
if ((btflags[bt[myobj2->y][myobj2->x]&1023]&1)==0) goto nospaceforbody;
if ((btflags[bt[myobj2->y][myobj2->x-1]&1023]&1)==0) goto nospaceforbody;
if (od[myobj2->y][myobj2->x]->next) goto nospaceforbody;
if (od[myobj2->y][myobj2->x-1]) goto nospaceforbody;
}
myobj5=OBJnew();
myobj5->type=mover_body[myobj2->type&1023];
if ((mover_body[myobj2->type&1023]>=432)&&(mover_body[myobj2->type&1023]<=447)){
myobj5->type|=(myobj2->type>>10<<10);
}
myobj5->info|=112;
//edit type if/as necessary
//4 part
if (((myobj2->type&1023)==344)||((myobj2->type&1023)==347)||((myobj2->type&1023)==353)||((myobj2->type&1023)==356)){
myobj5->type=(myobj5->type&1023)+(int(rnd*4)*1024);
}
//8 part flappers
if (((myobj2->type&1023)==369)||((myobj2->type&1023)==372)){
if ((myobj5->type&1024)==0){
myobj5->type=myobj5->type+(int(rnd*2)*1024);
}
}
if (mover_blood[myobj2->type&1023]){
if ((mover_body[myobj2->type&1023]>=432)&&(mover_body[myobj2->type&1023]<=447)){
myobj4->type=338+(((myobj5->type>>10)%3)<<10);
}
}
if (myobj4){
if (myobj6=od[myobj2->y][myobj2->x]){
od[myobj2->y][myobj2->x]=myobj4; myobj4->next=myobj6; myobj6->prev=myobj4;
myobj4->x=myobj2->x; myobj4->y=myobj2->y;
}else{
OBJadd(myobj2->x,myobj2->y,myobj4);
}
}
/*
if (((obj->type&1023)>=432)&&((obj->type&1023)<=447)){//blood of dead crt
im32z(ps,GSx,GSy,spr84[3],171+((obj->type>>10)%3));
}
*/
OBJadd(myobj2->x,myobj2->y,myobj5);
if ((mover_body[myobj2->type&1023]==(340+1024*3))||(mover_body[myobj2->type&1023]==(341+1024*3))){
myobj4=OBJnew(); myobj4->type=myobj5->type-1024; myobj4->info|=112; myobj4->info|=8; myobj4->more=myobj5;
OBJadd(myobj2->x-1,myobj2->y,myobj4);
myobj4=OBJnew(); myobj4->type=myobj5->type-2048; myobj4->info|=112; myobj4->info|=8; myobj4->more=myobj5;
OBJadd(myobj2->x,myobj2->y-1,myobj4);
myobj4=OBJnew(); myobj4->type=myobj5->type-3072; myobj4->info|=112; myobj4->info|=8; myobj4->more=myobj5;
OBJadd(myobj2->x-1,myobj2->y-1,myobj4);
}
if (mover_body[myobj2->type&1023]==(134+1024*1)){
myobj4=OBJnew(); myobj4->type=myobj5->type-1024; myobj4->info|=112; myobj4->info|=8; myobj4->more=myobj5;
OBJadd(myobj2->x-1,myobj2->y,myobj4);
}
if (myobj4=(object*)crt->items->more){
myobj4->prev=myobj5;
myobj5->more=myobj4;
crt->items->more=NULL;
}
}else{
nospaceforbody:
if (myobj4){
if (myobj6=od[myobj2->y][myobj2->x]){
od[myobj2->y][myobj2->x]=myobj4; myobj4->next=myobj6; myobj6->prev=myobj4;
myobj4->x=myobj2->x; myobj4->y=myobj2->y;
}else{
OBJadd(myobj2->x,myobj2->y,myobj4);
}
}
//drop gold/items at death spot!
myobj4=(object*)crt->items->more; //will point to first item
dropgoldmore:
if (myobj4){
myobj5=(object*)myobj4->next;
OBJmove_allow=TRUE;
OBJmove(myobj4,myobj2->x,myobj2->y);
OBJmove_allow=FALSE;
myobj4->info|=112; //set flags as temp OBJ
if (myobj5) {myobj4=myobj5; goto dropgoldmore;}
}
}
if (crt->al==1){ //only add exp if agressive
//amulet of submission check (no exp + karma loss for attacking gargoyles)
if (((myobj2->type&1023)==362)||((myobj2->type&1023)==363)){//gargoyle
if (myobj2->x>=1024){ if (myobj2->y>=256){
if (myobj2->x<1280){ if (myobj2->y<512){
tplayer3=tnpc->player;
if (tplayer3->GNPCflags[12]){
tplayer3->karma-=2; txtset(t,"?You feel less virtuous than before!"); t->d2[0]=8; NET_send(NETplayer,tplayer3->net,t);
goto noexp;
}
for (x2=1;x2<=7;x2++){
if (tplayer3->party[x2]){
if (((npc*)tplayer3->party[x2]->more)->converse==162){
tplayer3->karma-=2; txtset(t,"?You feel less virtuous than before!"); t->d2[0]=8; NET_send(NETplayer,tplayer3->net,t);
goto noexp;
}
}//tplayer3->party[x2]
}//x2
}}}}//x,y,x,y
}//gargoyle
tnpc->exp+=obji[sprlnk[myobj2->type&1023]].v5; //*needs to change
//Inexperienced character armour bonus changed to 50%
if (tnpc->player){ if (tnpc->player->party[0]){ if ((npc*)tnpc->player->party[0]->more==tnpc){ if (tnpc->exp<1600){ if (tnpc->lev<=2){
//tnpc->arm+=(20-tnpc->exp/80);
tnpc->upflags|=64;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Inexperienced character armour bonus is "); txtnumint(t2,100-tnpc->exp/16); txtadd(t,t2); txtadd(t,"%"); NET_send(NETplayer,tnpc->player->net,t);
}}}}}
tnpc->upflags|=8;
}//al==1
}//->craft
}//tnpc
noexp:
//passive turned agressive cat? if so set global flag
if (tplayer3=tnpc->player){
if (crt->al==3){//passive turned agressive
if ((myobj2->type&1023)==388){//cat
tplayer3->GNPCflags[36]=1;
}//cat
}//3
}//->player
crtrespawn(myobj2);
if (spellattcrt) {spellattcrt=FALSE; goto spellattcrt1;}
//object can now safely be destroyed (if not in update list)
myobj2=NULL; goto attackdone;
}
if (spellattcrt) {spellattcrt=FALSE; goto spellattcrt1;}
attack_item_skip2:;
}//(x)
}//i3
attackdone:
if (spikedhelm_attack){
spikedhelm_attack=0;//clear set variables
if (myobj2){
myobj3=NULL;
i3=1;
wep_dt[1]=1;
x=4;
goto spikedhelm_entrypoint;
}
}
if (triplecrossbow_shot){
triplecrossbow_miss:
triplecrossbow_shot--;
if (triplecrossbow_shot){ //2nd shot
x6=4; //75% chance of bolt recovery
myobj2=OBJfindlast(triplecrossbow_shot_x2,triplecrossbow_shot_y2); if (myobj2==NULL) myobj2=OBJfindlastall(triplecrossbow_shot_x2,triplecrossbow_shot_y2);
if (myobj2){
//if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
x7=rnd*(tnpc->d+1); x8=rnd*16; if (x7>=x8){ //didn't miss!
i3=1;
wep_dt[0]=3; wep_dt[1]=3;
x=12;
i4=SFnew(myobj2->x,myobj2->y);
sf[i4].type=1; //attack
sf[i4].x=triplecrossbow_shot_x2;
sf[i4].y=triplecrossbow_shot_y2;
sf[i4].x2=0;
sf[i4].wait=0.125f; //NULL
sf[i4].more=1;
goto triplecrossbow_refire;
}//didn't miss
x6=2; //50% chance of bolt recovery
}//crt
}//myobj2
x7=rnd*x6; if (x7){ //recover bolt
if (myobj2) if (myobj2->info&2) x6=2; //npc
if (x6==2){ //x6: bolt under crt/npc
myobj9=OBJnew();
AUTOPICKUPadd(myobj,myobj9);
myobj9->type=56;
myobj9->more2=1;
myobj9->prev=myobj2->prev; myobj9->x=myobj2->x; myobj9->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj9;
}else{
od[myobj2->y][myobj2->x]=myobj9;
}
myobj2->prev=myobj9;
myobj9->next=myobj2;
myobj9->info|=112; //set flags as temp OBJ
myobj9->x=myobj2->x; myobj9->y=myobj2->y;
OBJcheckflags(myobj9->x,myobj9->y);
}else{ //x6: bolt on ground
if (bt[triplecrossbow_shot_y2][triplecrossbow_shot_x2]&1024){ //walkable
myobj9=OBJnew(); myobj9->type=56; myobj9->more2=1; myobj9->info=112; OBJadd(triplecrossbow_shot_x2,triplecrossbow_shot_y2,myobj9);
AUTOPICKUPadd(myobj,myobj9);
}//walkable
}//x6
}//x7
triplecrossbow_shot--;
}//triplecrossbow_shot
//3rd/final shot
/*
x7=rnd*(tnpc->d+1); x8=rnd*16; if (x7<x8) goto triplecrossbow_miss2;
myobj2=OBJfindlast(triplecrossbow_shot_x3,triplecrossbow_shot_y3); if (myobj2==NULL) myobj2=OBJfindlastall(triplecrossbow_shot_x3,triplecrossbow_shot_y3);
if (myobj2){
//if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
i3=1;
x=12;
wep_dt[0]=3; wep_dt[1]=3;
i4=SFnew(myobj2->x,myobj2->y);
sf[i4].type=1; //attack
sf[i4].x=triplecrossbow_shot_x3;
sf[i4].y=triplecrossbow_shot_y3;
sf[i4].x2=0;
sf[i4].wait=0.125f; //NULL
sf[i4].more=1;
goto triplecrossbow_refire;
}
}
*/
x6=4; //75% chance of bolt recovery
myobj2=OBJfindlast(triplecrossbow_shot_x3,triplecrossbow_shot_y3); if (myobj2==NULL) myobj2=OBJfindlastall(triplecrossbow_shot_x3,triplecrossbow_shot_y3);
if (myobj2){
//if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
x7=rnd*(tnpc->d+1); x8=rnd*16; if (x7>=x8){ //didn't miss!
i3=1;
wep_dt[0]=3; wep_dt[1]=3;
x=12;
i4=SFnew(myobj2->x,myobj2->y);
sf[i4].type=1; //attack
sf[i4].x=triplecrossbow_shot_x3;
sf[i4].y=triplecrossbow_shot_y3;
sf[i4].x2=0;
sf[i4].wait=0.125f; //NULL
sf[i4].more=1;
goto triplecrossbow_refire;
}//didn't miss
x6=2; //50% chance of bolt recovery
}//crt
}//myobj2
x7=rnd*x6; if (x7){ //recover bolt
if (myobj2) if (myobj2->info&2) x6=2; //npc
if (x6==2){ //x6: bolt under crt/npc
myobj9=OBJnew();
AUTOPICKUPadd(myobj,myobj9);
myobj9->type=56;
myobj9->more2=1;
myobj9->prev=myobj2->prev; myobj9->x=myobj2->x; myobj9->y=myobj2->y;
if (myobj2->prev){
myobj4=(object*)myobj2->prev;
myobj4->next=myobj9;
}else{
od[myobj2->y][myobj2->x]=myobj9;
}
myobj2->prev=myobj9;
myobj9->next=myobj2;
myobj9->info|=112; //set flags as temp OBJ
myobj9->x=myobj2->x; myobj9->y=myobj2->y;
OBJcheckflags(myobj9->x,myobj9->y);
}else{ //x6: bolt on ground
if (bt[triplecrossbow_shot_y3][triplecrossbow_shot_x3]&1024){ //walkable
myobj9=OBJnew(); myobj9->type=56; myobj9->more2=1; myobj9->info=112; OBJadd(triplecrossbow_shot_x3,triplecrossbow_shot_y3,myobj9);
AUTOPICKUPadd(myobj,myobj9);
}//walkable
}//x6
}//x7
}//triplecrossbow_shot: end
}//x>0 attack possible
else
{//attack was NOT possible, close in on target!
if (miss){ //miss!
if (tplayer->craft==NULL) OBJdir(myobj,myobj2->x,myobj2->y);
f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
tnpc->wait_attack+=2.0-(f*0.25f);
goto skipnpcattack;
}
attacknotpossible:
if (selected_partymember) goto skipnpcattack; //movement is manual
if (tnpc->wait_walk) goto skipnpcattack; //can't move closer anyway!
npcattackclose:
myobj2=tnpc->target; //activeplayer->party[activeplayer->selected_partymember];
x2=0; y2=0;
WPF_NEXTTO=1; WPF_OBJECT=myobj; wpf_pathfind(tnpc->path,myobj->x,myobj->y,myobj2->x,myobj2->y,32,0,2);
x3=0;
if (WPF_RETURN==WPF_PATHFOUND){
x3=WPF_PATHLENGTH;
}
if (x3==0){//can't get within rage of target! or ALREADY THERE!
tnpc->order=1; tnpc->follow=tplayer->party[tplayer->selected_partymember]; goto skipnpcattack;
}
/*
PATHFIND_NEXTTO=1; x3=pathfind(tnpc->path,myobj->x,myobj->y,myobj2->x,myobj2->y,1);
if ((x3>32)||(x3==0)) {PATHFIND_NEXTTO=1; x3=pathfind(tnpc->path,myobj->x,myobj->y,myobj2->x,myobj2->y,NULL);}
if ((x3>32)||(x3==0)){ //can't get within rage of target! or ALREADY THERE!
tnpc->order=1; tnpc->follow=tplayer->party[tplayer->selected_partymember]; goto skipnpcattack;
}
*/
if (tnpc->path[0]==PFright) x2=1;
if (tnpc->path[0]==PFleft) x2=-1;
if (tnpc->path[0]==PFup) y2=-1;
if (tnpc->path[0]==PFdown) y2=1;
x3=0;
if (x2){
if (OBJmove2(myobj,myobj->x+x2,myobj->y)==0) x3++;
}
if ((y2)&&(x3==0)){
if (OBJmove2(myobj,myobj->x,myobj->y+y2)==0) x3++;
}
if (x3){
f=(float)tnpc->d/64.0f; if (f>1.0f) f=1.0f;
tnpc->wait_walk+=(0.25f-0.0625f-f*0.125f);
}
} //close in on target (couldn't attack)
skipnpcattack:;
} //end attack
//} //NPC, not selected partymember
NPC_skip1:; //NPC (not player/party) skip
} //CRITICAL ERROR CORRECT
} //NPCtype
donemove:;
skip_ouli:;
}//oul[i]!=NULL
}//i
}//oul!=0
u6opi=5;
for (tpl=0;tpl<=playerlist_last;tpl++){ //process INPUT
if (playerlist[tpl]){ //current player
tplayer=playerlist[tpl];
if (tplayer->mobj){
tplayer->mobj->info|=112; //set mobj flags as temp OBJ
if ((tplayer->mobj->type&1023)==223){ //powder keg
tplayer->mobj->more2=tplayer->id; //id
if (tplayer->mobj->type!=223){
tplayer->mobj->type=223;
tplayer->mobj_last=NULL; //update message: mobj has changed
}
}//223
if ((tplayer->mobj->type&1023)==173){ //trap
tplayer->mobj->more2=tplayer->id; //id
}//173
//set "new" horse owner in respawn_y
if (tplayer->mobj->type==448){
if (myobj=(object*)tplayer->mobj->more){
//GPF latest
if (myobj->info&4){//crt
crt=(creature*)myobj->more;
crt->respawn_y=tpl;
}//crt
}//->more
}//448
}//mobj
//followers resurrection
if (tplayer->respawn==254){
tplayer->respawn=0;
if (tplayer->party[0]==NULL){
txtsetchar(t,8); txtadd(t,"You must first resurrect yourself!"); NET_send(NETplayer,tplayer->net,t);
goto resurrectfollowers_failed;
}
if (tplayer->craft){
txtsetchar(t,8); txtadd(t,"Not now!"); NET_send(NETplayer,tplayer->net,t);
goto resurrectfollowers_failed;
}
i2=0;
for (i=0;i<=nresu;i++){
if (resu[i]){
if (resu_player[i]==tplayer){
if (resu_partymember[i]>=1){
i2=1;
tplayer->party[resu_partymember[i]]=resu[i];
tnpc=(npc*)resu[i]->more; tnpc->exp-=(tnpc->exp/8);
resu[i]=NULL;
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[resu_partymember[i]],tplayer->party[0]->x,tplayer->party[0]->y);
OBJmove_allow=FALSE;
txtset(t5,"?"); t5->d2[0]=8; txtadd(t5,tnpc->name); txtadd(t5," resurrected. (F1)");
for (x2=0;x2<=playerlist_last;x2++){ //create and send UPDATE message
if (playerlist[x2]){ //current player
if (playerlist[x2]->net!=INVALID_NET){ //net connection available
if (playerlist[x2]->party[0]){
NET_send(NETplayer,playerlist[x2]->net,t5);
}}}}
}//0
}//player
}//resu
}//i
if (i2) {inbritanniacheck(); goto resurrectfollowers_failed;}
txtsetchar(t,8); txtadd(t,"None of your followers are dead!"); NET_send(NETplayer,tplayer->net,t);
}//respawn
resurrectfollowers_failed:
//self-resurrection?
if (tplayer->respawn==255){
tplayer->respawn=0;
//check ressurection tables for player's pointer
//return player to party[0]
for (i=0;i<=nresu;i++){
if (resu[i]){
if (resu_player[i]==tplayer){
if (resu_partymember[i]==0){
/*
object *resu[65536]; //object
object *resu_body[65536]; //dead body object
float resu_wait[65536]; //time until object automatically resurrected
player *resu_player[65536]; //player object belongs to
unsigned char resu_partymember[65536]; //party member index
long nresu=-1;
*/
tplayer->party[0]=resu[i];
if (tplayer->GNPCflags[25]==0) {
tnpc=(npc*)resu[i]->more; tnpc->exp-=(tnpc->exp/8);//res by f1
x2=256+128-16;
y2=256+128+2;
}
else { //resurrect at brit healer's bed and remove insurance
tplayer->GNPCflags[25]=0;
x2=362;
y2=362;
}
resu[i]=NULL;
for (x4=1;x4<=7;x4++){
if (tplayer->party[x4]){
tnpc2=(npc*)tplayer->party[x4]->more; tnpc2->upflags=1;
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[x4],x2,y2); //place party on the map
OBJmove_allow=FALSE;
}
}//x4
OBJmove_allow=TRUE;
OBJmove2(tplayer->party[0],x2,y2); //place avatar on the map
OBJmove_allow=FALSE;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"A voice in the darkness intones, \x022KAL LOR!\x022"); NET_send(NETplayer,tplayer->net,t);
txtset(t5,"?"); t5->d2[0]=8; txtadd(t5,tnpc->name); txtadd(t5," resurrected. (F1)");
for (x2=0;x2<=playerlist_last;x2++){ //create and send UPDATE message
if (playerlist[x2]){ //current player
if (playerlist[x2]->net!=INVALID_NET){ //net connection available
if (playerlist[x2]->party[0]){
if (playerlist[x2]!=tplayer){
NET_send(NETplayer,playerlist[x2]->net,t5);
}}}}}
inbritanniacheck();
goto resurrect_failed;
}//0
}//player
}//resu
}//i
txtsetchar(t,8); txtadd(t,"You are not dead!"); NET_send(NETplayer,tplayer->net,t);
}//respawn
resurrect_failed:
if (playerlist[tpl]->party[0]){
//move selected party member
//tplayer=playerlist[tpl];
myobj=tplayer->party[tplayer->selected_partymember];
tnpc=(npc*)myobj->more;
//tpx=myobj->x-15; tpy=myobj->y-11;
//if (tpx<0) tpx=0;
//if (tpy<0) tpy=0;
//if (tpx>2016) tpx=2016;
//if (tpy>1000) tpy=1000;
getscreenoffset(myobj->x,myobj->y,&tpx,&tpy);
//cast spell
if (tplayer->key&KEYmbclick){
i=tplayer->mf;
//change party member?
if ((i>=16)&&(i<=23)){
if (tplayer->craft==NULL){
i-=16;
x=0;
for (i2=0;i2<=7;i2++){
if (tplayer->party[i2]){
if (x==i){
if (tplayer->party[i2]->x){ //not in the void!
tplayer->selected_partymember=i2;
tplayer->pathfind=0;
goto switchpartymember;
}
}
x++;
}//->party[i2]
}//i2
}//craft
goto skip_pickup;
switchpartymember:
for (x2=0;x2<=7;x2++){ if (tplayer->party[x2]){
myobj2=tplayer->party[x2]; tnpc=(npc*)myobj2->more;
tnpc->follow=tplayer->party[tplayer->selected_partymember];
if (x2==tplayer->selected_partymember){
if (tnpc->order!=3) tnpc->order=0;
}else{
if (tnpc->order!=3) tnpc->order=1;
}
}}
goto skip_pickup;
}
if (i==24){ //staff cast
myobj=tplayer->staffcast_npc;
tnpc=(npc*)myobj->more;
//x2=tplayer->staffcast_staff->more2&65535;
staff_cast_spell=1;
goto staffcast0;
}
if ((i>=8)&&(i<=15)){
static unsigned char iparty; iparty=i-8;
myobj=tplayer->party[i-8];
if(!myobj) {
goto castfailed;
}
tnpc=(npc*)myobj->more;
cast_spell0:
staff_cast_spell=0;
staffcast0:
if (stormcloakcheck2(myobj->x,myobj->y,tplayer)){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," cannot cast magic at this time!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
CASTSPELL_SPELLTYPE=0;
static long CASTSPELL_ENUMERATEDINVENTORYOBJS;
CASTSPELL_ENUMERATEDINVENTORYOBJS=0;
if (!staff_cast_spell){
//enumerate reagents!
ZeroMemory(&treagent,sizeof(treagent));
x4=OBJlist((object*)tnpc->items->more);
OBJlist_last=NULL;
for(x5=0;x5<x4;x5++){
x3=OBJlist_list[x5]->type;
if ((x3>=65)&&(x3<=72)){
treagent[x3-65]+=OBJlist_list[x5]->more2;
}
}
CASTSPELL_ENUMERATEDINVENTORYOBJS=x4; //number of inventory objects
}//!staff_cast_spell
if (!cast_spell){
x=tplayer->mx; y=tplayer->my&255;
//fix x and y if using ktar
if (x&32768){ //spell ktar
x-=32768;
if ((x>=0)&&(x<=9)){
if (tplayer->ktar_wait[x]){
if (tplayer->ktar[x]->more){
myobj3=(object*)tplayer->ktar[x]->more;
crt=(creature*)myobj3->more; if (crt->flags&2) goto castfailed;
y=myobj3->y-tpy;
x=myobj3->x-tpx;
goto ktarcast2;
}//ktar
}//wait
}//x
goto castfailed;
}
ktarcast2:
CASTSPELL_SPELLTYPE=tplayer->my>>8;
}
if (staff_cast_spell) CASTSPELL_SPELLTYPE=tplayer->staffcast_staff->more2&65535;
i2=0; //set to 1 if cast successful
if (tplayer->craft){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Not while aboard ship!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
if (!staff_cast_spell){
if (tnpc->lev<((CASTSPELL_SPELLTYPE>>4)+1)){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," is not ready for this circle!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
//check if spell actually exists in spellbook (safeguard!)
ZeroMemory(&tspell,sizeof(tspell));
//enumerate spells
if (myobj2=(object*)tnpc->wep_left){ if (myobj2->type==57){
myobj2=(object*)myobj2->more;
nextspell3:
if (myobj2){
tspell[myobj2->more2]=1;
if (myobj2->next) {myobj2=(object*)myobj2->next; goto nextspell3;}
}
}}
if (myobj2=(object*)tnpc->wep_right){ if (myobj2->type==57){
myobj2=(object*)myobj2->more;
nextspell4:
if (myobj2){
tspell[myobj2->more2]=1;
if (myobj2->next) {myobj2=(object*)myobj2->next; goto nextspell4;}
}
}}
if (tspell[CASTSPELL_SPELLTYPE]==0){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No spell!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
//check reagents for spell
for (x3=0;x3<=7;x3++){
if (spellreagent[CASTSPELL_SPELLTYPE]&(1<<x3)){
if (treagent[x3]==0){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"No reagents!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
}
}
//check spellpoints for spell
if (tnpc->mp<((CASTSPELL_SPELLTYPE>>4)+1)){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Not enough magic points!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
}//!staff_cast_spell
//in range?
if ((abs((tpx+x)-myobj->x)>8)||(abs((tpy+y)-myobj->y)>8)){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Out of range!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
if (tnpc->wait_cast||tnpc->wait_disable){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," busy!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
//staff enchant?
if (CASTSPELL_SPELLTYPE!=((6<<4)+1)){//not the enchant spell
if (myobj2=OBJfindlast(tpx+x,tpy+y)){
i2=2;
if (myobj2->type==78){//dest location has a staff
if ((CASTSPELL_SPELLTYPE==(myobj2->more2&65535))||((myobj2->more2&65535)==0)){
x3=(myobj2->info>>9)&7;
if (x3){//enchantment possible!
if (OBJcheckbolt(myobj->x,myobj->y,tpx+x,tpy+y)){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Blocked!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
i2=1;
myobj2->more2|=CASTSPELL_SPELLTYPE;
myobj2->info=myobj2->info&(0xFFFF-(7<<9)); x3--; myobj2->info|=(x3<<9);
x3=myobj2->more2>>16;
myobj2->more2=myobj2->more2&0xFFFF; x3++; myobj2->more2|=(x3<<16);
txtset(t,"?"); t->d2[0]=8;
txtadd(t,"Staff successfully enchanted with the ");
txtset(t2,spellname[CASTSPELL_SPELLTYPE]);
txtlcase(t2);
txtadd(t,t2);
txtadd(t," spell (x");
txtnumint(t2,myobj2->more2>>16); txtadd(t,t2);
txtadd(t,").");
if ((myobj2->info>>9)&7){
txtadd(t," ");
txtnumint(t2,(myobj2->info>>9)&7); txtadd(t,t2);
txtadd(t," more enchantments left.");
}
NET_send(NETplayer,tplayer->net,t);
goto spelldone;
}//x3
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You must cast enchant upon this staff before enchanting it with spells!"); NET_send(NETplayer,tplayer->net,t);
goto spelldone;
}//CASTSPELL_SPELLTYPE
goto spelldone;
}//staff
}//findlast
}//CASTSPELL_SPELLTYPE!=enchant spell
//3. cast spell
static long spellx,spelly,spellx2,spelly2,spellz,spellz2;
if (CASTSPELL_SPELLTYPE==((6<<4)+9)){ //wizard eye //txtset(spellname[(6<<4)+9],"WizardEye"); spellreagent[(6<<4)+9]=BLOO|NIGH|MAND|SULF|BLAC|SPID;
i2=2; //implemented!
if (tnpc->player->wizardeyetimeleft==0.0f){
if (i9=rnd*(tnpc->i+1)){
i2=1;
tnpc->player->wizardeyetimeleft=i9; tnpc->player->wizardeyemovewait=0.0f;
tnpc->player->wizardeyex=myobj->x; tnpc->player->wizardeyey=myobj->y;
txtset(t,"??"); t->d2[0]=36; t->d2[1]=i9; NET_send(NETplayer,tnpc->player->net,t);
}else{
i2=3;
}
}//timeleft==0
goto spelldone;
}//wizardeye
if (CASTSPELL_SPELLTYPE==((2<<4)+7)){ //peer txtset(spellname[(2<<4)+7],"Peer"); spellreagent[(2<<4)+7]=NIGH|MAND;
i2=2; //implemented!
x3=rnd*(8+5*3);
x4=rnd*(tnpc->i+10);
if (x4>=x3){//success
x3=rnd*(32+(tnpc->i>>3));
if (x3){
if (x3>255) x3=255; //cap
if (x3>tnpc->player->peer){
tnpc->player->peer=x3;
//send peer update message, changed to 48, 34 was already in use, but not in client side, so I don't know if it messed up anything or not. probably not
txtset(t,"??"); t->d2[0]=48; t->d2[1]=tnpc->player->peer; NET_send(NETplayer,tnpc->player->net,t);
}
i2=1;
}
if (x3==0) i2=3;
} else {i2=3;} //fail
goto spelldone;
}//peer
//txtset(spellname[(1<<4)+5],"Telekinesis"); spellreagent[(1<<4)+5]=BLOO|MAND|BLAC;
if (CASTSPELL_SPELLTYPE==((1<<4)+5)) { //telekinesis
i2=spell_telekinesis(tplayer,tnpc,NULL,tpx+x,tpy+y);
goto spelldone;
}//telekinesis
if (CASTSPELL_SPELLTYPE==((7<<4)+0)){//death wind //txtset(spellname[(7<<4)+0],"DeathWind"); spellreagent[(7<<4)+0]=MAND|NIGH|SULF|BLOO; //level 8
i2=2;
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
spellx=tpx+x; spelly=tpy+y;
getwindspell(myobj->x,myobj->y,spellx,spelly);
//add special effects
for (z=0;z<=WINDSPELL_boltn;z++){
z2=SFnew(WINDSPELL_boltx[z],WINDSPELL_bolty[z]);
sf[z2].type=25;//multiple death bolts
sf[z2].x=myobj->x;
sf[z2].y=myobj->y;
sf[z2].x2=WINDSPELL_boltx[z];
sf[z2].y2=WINDSPELL_bolty[z];
sf[z2].more=0xFFFF;
sf[z2].wait=1;
}//z
for (spellz=0;spellz<=WINDSPELL_n;spellz++){
if (spellx=WINDSPELL_x[spellz]){
spelly=WINDSPELL_y[spellz];
if (stormcloakcheck2(spellx,spelly,tplayer)==0){
myobj2=OBJfindlast(spellx,spelly); if (myobj2==NULL) myobj2=OBJfindlastall(spellx,spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(512+tnpc->i*8);
x3=rnd*(512+tnpc->i*8);
x2=((x2+x3)>>1);
if (x2<crt->hp) {i2=1; x2=i8; i3=i9; goto deathwind_spelldone;}
i3=myobj2->type&1023;
if (i3==352) {x2=0; goto IDimmunedeath8;} //ghost
if (i3==368) {x2=0; goto IDimmunedeath8;} //skeleton
if (i3==373) {x2=0; goto IDimmunedeath8;} //wisp
if (i3==367) {x2=0; goto IDimmunedeath8;} //daemon
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
IDimmunedeath8:
spellattcrt=TRUE; goto spellattcrt0;
}//myobj2
}//crt
}//stormcloakcheck2
}//spellx check
deathwind_spelldone:;
}//spellz
i2=1;
goto spelldone;
}//deathwind
if (CASTSPELL_SPELLTYPE==((6<<4)+2)){//energy wind //txtset(spellname[(6<<4)+2],"EnergyWind"); spellreagent[(6<<4)+2]=MAND|NIGH|SULF|BLOO;
i2=2;
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
spellx=tpx+x; spelly=tpy+y;
getwindspell(myobj->x,myobj->y,spellx,spelly);
//add special effects
for (z=0;z<=WINDSPELL_boltn;z++){
z2=SFnew(WINDSPELL_boltx[z],WINDSPELL_bolty[z]);
sf[z2].type=24;//multiple lightning!
sf[z2].x=myobj->x;
sf[z2].y=myobj->y;
sf[z2].x2=WINDSPELL_boltx[z];
sf[z2].y2=WINDSPELL_bolty[z];
sf[z2].more=0xFFFF;
sf[z2].wait=1;
}//z
for (spellz=0;spellz<=WINDSPELL_n;spellz++){
if (spellx=WINDSPELL_x[spellz]){
spelly=WINDSPELL_y[spellz];
if (stormcloakcheck2(spellx,spelly,tplayer)==0){
myobj2=OBJfindlast(spellx,spelly); if (myobj2==NULL) myobj2=OBJfindlastall(spellx,spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(64+tnpc->i*2);
if (x2==0) {i2=3; x2=i8; i3=i9; goto energywind_spelldone;}
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
spellattcrt=TRUE; goto spellattcrt0;
}//myobj2
}//crt
}//stormcloakcheck2
}//spellx check
energywind_spelldone:;
}//spellz
i2=1;
goto spelldone;
}//energywind
if (CASTSPELL_SPELLTYPE==((5<<4)+7)){//poison wind //txtset(spellname[(5<<4)+7],"PoisonWind"); spellreagent[(5<<4)+7]=NIGH|SULF|BLOO;
i2=2;
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
spellx=tpx+x; spelly=tpy+y;
getwindspell(myobj->x,myobj->y,spellx,spelly);
//add special effects
for (z=0;z<=WINDSPELL_boltn;z++){
z2=SFnew(WINDSPELL_boltx[z],WINDSPELL_bolty[z]);
sf[z2].type=23;//multiple green balls
sf[z2].x=myobj->x;
sf[z2].y=myobj->y;
sf[z2].x2=WINDSPELL_boltx[z];
sf[z2].y2=WINDSPELL_bolty[z];
sf[z2].more=0xFFFF;
sf[z2].wait=1;
}//z
for (spellz=0;spellz<=WINDSPELL_n;spellz++){
if (spellx=WINDSPELL_x[spellz]){
spelly=WINDSPELL_y[spellz];
if (stormcloakcheck2(spellx,spelly,tplayer)==0){
myobj2=OBJfindlast(spellx,spelly); if (myobj2==NULL) myobj2=OBJfindlastall(spellx,spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
x3=rnd*(8+5*2);
x4=rnd*(tnpc->i+10);
if (x4>=x3){//success
crt->flags|=1;
z2=SFnew(myobj2->x,myobj2->y);
sf[z2].type=1; //attack
sf[z2].x2=0;
sf[z2].x=myobj2->x;
sf[z2].y=myobj2->y;
sf[z2].wait=0.125f; //NULL
sf[z2].more=1;
}//success
}//crt
}//myobj2
}//stormcloakcheck2
}//spellx check
}//spellz
i2=1;
goto spelldone;
}//poisonwind
if (CASTSPELL_SPELLTYPE==((5<<4)+3)){//flame wind //txtset(spellname[(5<<4)+3],"FlameWind"); spellreagent[(5<<4)+3]=SULF|BLOO|MAND;
i2=2;
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
spellx=tpx+x; spelly=tpy+y;
getwindspell(myobj->x,myobj->y,spellx,spelly);
//add special effects
for (z=0;z<=WINDSPELL_boltn;z++){
z2=SFnew(WINDSPELL_boltx[z],WINDSPELL_bolty[z]);
sf[z2].type=22;//multiple fireballs
sf[z2].x=myobj->x;
sf[z2].y=myobj->y;
sf[z2].x2=WINDSPELL_boltx[z];
sf[z2].y2=WINDSPELL_bolty[z];
sf[z2].more=0xFFFF;
sf[z2].wait=1;
}//z
for (spellz=0;spellz<=WINDSPELL_n;spellz++){
if (spellx=WINDSPELL_x[spellz]){
spelly=WINDSPELL_y[spellz];
if (stormcloakcheck2(spellx,spelly,tplayer)==0){
myobj2=OBJfindlast(spellx,spelly); if (myobj2==NULL) myobj2=OBJfindlastall(spellx,spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(48+tnpc->i+(tnpc->i>>1));
if (x2==0) {i2=1; x2=i8; i3=i9; goto flamewind_spelldone;}
//fire resistant???
i3=myobj2->type&1023;
if (i3==411) {x2=0; goto IFimmuneflame4;} //dragon
if (i3==369) {x2=0; goto IFimmuneflame4;} //drake
if (i3==352) {x2=0; goto IFimmuneflame4;} //ghost
if (i3==374) {x2=0; goto IFimmuneflame4;} //hydra
if (i3==369) {x2=0; goto IFimmuneflame4;} //drake
if (i3==368) {x2=0; goto IFimmuneflame4;} //skeleton
if (i3==373) {x2=0; goto IFimmuneflame4;} //wisp
if (i3==367) {x2=0; goto IFimmuneflame4;} //daemon
//double damage?
if (i3==364) x2*=2; //acid slug
if (i3==357) x2*=2; //corpser
if (i3==347) x2*=2; //reaper
if (i3==360) x2*=2; //rot worms
if (i3==375) x2*=2; //slime
if (i3==365) x2*=2; //tangle vine
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
IFimmuneflame4:
spellattcrt=TRUE; goto spellattcrt0;
}//myobj2
}//crt
}//stormcloakcheck2
}//spellx check
flamewind_spelldone:;
}//spellz
i2=1;
goto spelldone;
}//flamewind
if (OBJcheckbolt(myobj->x,myobj->y,tpx+x,tpy+y)){
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Blocked!"); NET_send(NETplayer,tplayer->net,t);
}
goto castfailed;
}
//spell blocked???????????????????????????????????????????????
if (CASTSPELL_SPELLTYPE==((7<<4)+4)){ //resurrect //txtset(spellname[(7<<4)+4],"Resurrect"); spellreagent[(7<<4)+4]=GARL|GINS|SPID|SULF|BLOO|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2){
if ((myobj2->type&1023)==339){ //dead body
//***RESRTICTIONS: SOME PLACES IN BRITANNIA DEAD BODIES CANNOT BE RESURRECTED***
x4=tpx+x; y4=tpy+y;
//1. SACRED QUEST AREA x1 899 y1 811 x2 948 y2 872
if (x4>=899){ if (x4<=948){ if (y4>=811){ if (y4<=872){
goto spelldone;
}}}}
//2. PLAYER HOUSING
x6=housecheck(x4,y4);
if(x6) {
goto spelldone;
}
//3. PLAYER HOUSING - STORAGE
for (x5=1;x5<=255;x5++){
for (y5=0;y5<housestoragenext[x5];y5++){
if (x4==housestoragex[x5][y5]){ if (y4==housestoragey[x5][y5]){
goto spelldone;
}}//x,y
}//y5
}//x5
//4. WALKABLE SQUARE
if ((bt[y4][x4]&1024)==0){
goto spelldone;
}
//5. SHRINE IN THE VOID
if (x4>=1024){ if (x4<=1071){ if (y4>=0){ if (y4<=47){
goto spelldone;
}}}}
//scan resurrect list
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_body[i3]==myobj2){
if (resu_player[i3]){ //has a player pointer
//resurrection can be performed
i2=1;
x3=rnd*(8+5*8);
x4=rnd*(tnpc->i+50);
if (x4>=x3){//success
//resu_player[i3]->party[0]=resu[i3]; //assume current player
resu_player[i3]->party[resu_partymember[i3]]=resu[i3];
if (resu_partymember[i3]==0){
for (x4=1;x4<=7;x4++){
if (resu_player[i3]->party[x4]){
tnpc3=(npc*)resu_player[i3]->party[x4]->more; tnpc3->upflags=1;
OBJmove_allow=TRUE;
OBJmove2(resu_player[i3]->party[x4],myobj2->x,myobj2->y); //place party on the map
OBJmove_allow=FALSE;
}
}//x4
}
OBJmove_allow=TRUE;
OBJmove2(resu[i3],myobj2->x,myobj2->y); //place avatar on the map
OBJmove_allow=FALSE;
OBJremove(myobj2); //remove body
tnpc3=(npc*)resu[i3]->more;
resu[i3]=NULL;
txtset(t5,"?"); t5->d2[0]=8; txtadd(t5,"A voice in the darkness intones, \x022"); txtadd(t5,"IN MANI CORP!\x022"); NET_send(NETplayer,resu_player[i3]->net,t5);
txtset(t5,"?"); t5->d2[0]=8; txtadd(t5,tnpc3->name); txtadd(t5," resurrected by "); txtadd(t5,tnpc->name); txtadd(t5,".");
for (x3=0;x3<=playerlist_last;x3++){ //create and send UPDATE message
if (playerlist[x3]){ //current player
if (playerlist[x3]->net!=NULL){ //net connection available
if (playerlist[x3]->party[0]){
if (playerlist[x3]!=tplayer){
NET_send(NETplayer,playerlist[x3]->net,t5);
}}}}}
inbritanniacheck();
i2=1;
}else{i2=3;
if (resu_partymember[i3]==0) goto spelldone_donttakereagents;//add bug!
}
goto resurrect_spell_done;
}//player
}//resu_body==obj
}//resu
}//i3
}//dead body
}//myobj2
resurrect_spell_done:
goto spelldone;
}//resurrect
if (CASTSPELL_SPELLTYPE==((3<<4)+4)){ //great heal //txtset(spellname[(3<<4)+4],"GreatHeal"); spellreagent[(3<<4)+4]=GINS|SPID|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
//perform light heal (1 to 64->128 hp)
x3=rnd*(64+tnpc->i); //int can only double spell effectiveness!
x4=rnd*(64+tnpc->i); //int can only double spell effectiveness!
x3=(x3+x4)>>1;
tnpc2->hp+=x3; if (tnpc2->hp>tnpc2->hp_max) tnpc2->hp=tnpc2->hp_max;
tnpc2->upflags|=2;
i2=1;
if (x3==0) i2=3;
if (x3){
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
}//player
}//npc
}//myobj2
goto spelldone;
}//great heal
if (CASTSPELL_SPELLTYPE==((7<<4)+3)){ //mass kill! //txtset(spellname[(7<<4)+3],"MassKill"); spellreagent[(7<<4)+3]=BLAC|NIGH|MAND|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto masskillblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(512+tnpc->i*8);
x3=rnd*(512+tnpc->i*8);
x2=((x2+x3)>>1);
if (x2<crt->hp) {i2=1; x2=i8; i3=i9; goto masskill_spelldone;} //failed!
i3=myobj2->type&1023;
if (i3==352) {x2=0; goto IDimmunedeath2;} //ghost
if (i3==368) {x2=0; goto IDimmunedeath2;} //skeleton
if (i3==373) {x2=0; goto IDimmunedeath2;} //wisp
if (i3==367) {x2=0; goto IDimmunedeath2;} //daemon
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
IDimmunedeath2:
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
masskill_spelldone:;
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=15; //kill blast
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
masskillblocked:;
}//!=4
}}//spell x,y
i2=1;
goto spelldone;
}//mass kill!
if (CASTSPELL_SPELLTYPE==((3<<4)+2)){ //disable! //txtset(spellname[(3<<4)+2],"Disable"); spellreagent[(3<<4)+2]=NIGH|SPID|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
//x2=rnd*(256+tnpc->i*4);
//x3=rnd*(256+tnpc->i*4);
x2=rnd*(192+tnpc->i*3);
x3=rnd*(192+tnpc->i*3);
x2=((x2+x3)>>1);
if (x2<crt->hp) {i2=3; x2=i8; i3=i9; goto spelldone;} //failed!
x2=crt->hp-1;
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=15; //kill/disable blast
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
goto spelldone;
}//disable!
if (CASTSPELL_SPELLTYPE==((6<<4)+5)){ //kill! //txtset(spellname[(6<<4)+5],"Kill"); spellreagent[(6<<4)+5]=BLAC|NIGH|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(512+tnpc->i*8);
x3=rnd*(512+tnpc->i*8);
x2=((x2+x3)>>1);
if (x2<crt->hp) {i2=3; x2=i8; i3=i9; goto spelldone;} //failed!
i3=myobj2->type&1023;
if (i3==352) {x2=0; goto IDimmunedeath;} //ghost
if (i3==368) {x2=0; goto IDimmunedeath;} //skeleton
if (i3==373) {x2=0; goto IDimmunedeath;} //wisp
if (i3==367) {x2=0; goto IDimmunedeath;} //daemon
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
IDimmunedeath:
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=15; //kill blast
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
if (x2==0) {i2=3; x2=i8; i3=i9; goto spelldone;}
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
goto spelldone;
}//kill!
if (CASTSPELL_SPELLTYPE==((4<<4)+4)){ //lightning //txtset(spellname[(4<<4)+4],"Lightning"); spellreagent[(4<<4)+4]=BLAC|MAND|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(64+tnpc->i*2);
if (x2==0) {i2=3; x2=i8; i3=i9; goto spelldone;}
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=5;
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
goto spelldone;
}//lightning
if (CASTSPELL_SPELLTYPE==((6<<4)+0)){ //chain bolt //txtset(spellname[(6<<4)+0],"ChainBolt"); spellreagent[(6<<4)+0]=BLAC|MAND|SULF|BLOO; //level 7
static long chainbolt_hits,chainbolt_miss; chainbolt_hits=0; chainbolt_miss=0;
i2=2;//implemented!
spellx=tpx+x; spelly=tpy+y;
if (stormcloakcheck2(spellx,spelly,tplayer)) goto spelldone;
myobj2=OBJfindlast(spellx,spelly); if (myobj2==NULL) myobj2=OBJfindlastall(spellx,spelly);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
i2=3;
chainbolt_gotnexttarget:
chainbolt_miss=0;
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(64+tnpc->i*2);
if (x2==0) {x2=i8; i3=i9; goto chainbolt_spelldone;}
i2=1;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=5+chainbolt_hits*2*256;
if (chainbolt_hits){
sf[i3].x=spellx2;
sf[i3].y=spelly2;
}else{
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
}
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1+chainbolt_hits*2*256; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
spellattcrt=TRUE; goto spellattcrt0;
chainbolt_spelldone:
if (chainbolt_hits<=7){
//random scanning
spellx2=((long(rnd*17)-8)+(long(rnd*17)-8))/2; spelly2=((long(rnd*17)-8)+(long(rnd*17)-8))/2;
if (spellx2&&spelly2){//both not 0
spellx2+=spellx; spelly2+=spelly;
if (spellx2>=0){ if (spelly2>=0){ if (spellx2<2048){ if (spelly2<1024){//map boundries check
if (!stormcloakcheck2(spellx2,spelly2,tplayer)){
if (!OBJcheckbolt(spellx,spelly,spellx2,spelly2)){
myobj2=OBJfindlast(spellx2,spelly2); if (myobj2==NULL) myobj2=OBJfindlastall(spellx2,spelly2);
if (myobj2){
if (myobj2->info&4){ //<-crt
chainbolt_hits++;
i9=spellx; spellx=spellx2; spellx2=i9;
i9=spelly; spelly=spelly2; spelly2=i9;
goto chainbolt_gotnexttarget;
}//crt
}//myobj2
}//checkbolt
}//stormcloakcheck
}}}}//boundries
}//both not 0
chainbolt_miss++;
i9=128-chainbolt_hits*16+tnpc->i*2; if (chainbolt_miss<i9) goto chainbolt_spelldone;
}//chainbolthits
}//crt
}//myobj2
goto spelldone;
}//chainbolt
if (CASTSPELL_SPELLTYPE==((7<<4)+8)){ //tremor //txtset(spellname[(7<<4)+8],"Tremor"); spellreagent[(7<<4)+8]=BLOO|SULF|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
i2=1;
for (spelly2=tpy+y-23;spelly2<=tpy+y+23;spelly2++){
for (spellx2=tpx+x-31;spellx2<=tpx+x+31;spellx2++){
myobj2=OBJfindlast(spellx2,spelly2); if (myobj2==NULL) myobj2=OBJfindlastall(spellx2,spelly2);
if (myobj2){
if (myobj2->info&4){ //<-crt
if (spellx2>=0){ if (spelly2>=0){ if (spellx2<2048){ if (spelly2<1024){//map boundries check
if (!stormcloakcheck2(spellx2,spelly2,tplayer)){
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x3=abs(spellx2-(tpx+x)); x4=abs(spelly2-(tpy+y)); if (x4>x3) x3=x4;
x3*=3;
x2=rnd*(80+tnpc->i+(tnpc->i>>1));
x2-=x3;
if (x2<=0) {x2=i8; i3=i9; goto tremor_spelldone;}
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
spellattcrt=TRUE; goto spellattcrt0;
}//stormcloakcheck
}}}}//boundries
}}//myobj2,crt
tremor_spelldone:;
}}
i9=SFnew(tpx+x,tpy+y);
sf[i9].type=26;//tremor
sf[i9].wait=1;
goto spelldone;
}//tremor
if (CASTSPELL_SPELLTYPE==((4<<4)+1)){ //explosion //txtset(spellname[(4<<4)+1],"Explosion"); spellreagent[(4<<4)+1]=MAND|SULF|BLAC|BLOO;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto explosionblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(48+tnpc->i+(tnpc->i>>1));
if (x2==0) {i2=1; x2=i8; i3=i9; goto explosion_spelldone;}
//fire resistant???
i3=myobj2->type&1023;
if (i3==411) {x2=0; goto IFimmuneflame2;} //dragon
if (i3==369) {x2=0; goto IFimmuneflame2;} //drake
if (i3==352) {x2=0; goto IFimmuneflame2;} //ghost
if (i3==374) {x2=0; goto IFimmuneflame2;} //hydra
if (i3==369) {x2=0; goto IFimmuneflame2;} //drake
if (i3==368) {x2=0; goto IFimmuneflame2;} //skeleton
if (i3==373) {x2=0; goto IFimmuneflame2;} //wisp
if (i3==367) {x2=0; goto IFimmuneflame2;} //daemon
//double damage?
if (i3==364) x2*=2; //acid slug
if (i3==357) x2*=2; //corpser
if (i3==347) x2*=2; //reaper
if (i3==360) x2*=2; //rot worms
if (i3==375) x2*=2; //slime
if (i3==365) x2*=2; //tangle vine
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
IFimmuneflame2:
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
explosion_spelldone:;
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=8; //wand
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
explosionblocked:;
}//!=4
}}//spell x,y
i2=1;
goto spelldone;
}//explosion
if (CASTSPELL_SPELLTYPE==((2<<4)+2)){ //fireball //txtset(spellname[(2<<4)+2],"Fireball"); spellreagent[(2<<4)+2]=SULF|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(48+tnpc->i+(tnpc->i>>1));
if (x2==0) {i2=3; x2=i8; i3=i9; goto spelldone;}
//fire resistant???
i3=myobj2->type&1023;
if (i3==411) {x2=0; goto IFimmuneflame;} //dragon
if (i3==369) {x2=0; goto IFimmuneflame;} //drake
if (i3==352) {x2=0; goto IFimmuneflame;} //ghost
if (i3==374) {x2=0; goto IFimmuneflame;} //hydra
if (i3==369) {x2=0; goto IFimmuneflame;} //drake
if (i3==368) {x2=0; goto IFimmuneflame;} //skeleton
if (i3==373) {x2=0; goto IFimmuneflame;} //wisp
if (i3==367) {x2=0; goto IFimmuneflame;} //daemon
//double damage?
if (i3==364) x2*=2; //acid slug
if (i3==357) x2*=2; //corpser
if (i3==347) x2*=2; //reaper
if (i3==360) x2*=2; //rot worms
if (i3==375) x2*=2; //slime
if (i3==365) x2*=2; //tangle vine
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
IFimmuneflame:
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=8; //wand
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
goto spelldone;
}//fireball
if (CASTSPELL_SPELLTYPE==((1<<4)+1)){ //magic arrow //txtset(spellname[(1<<4)+1],"MagicArrow"); spellreagent[(1<<4)+1]=SULF|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(32+tnpc->i);
if (x2==0) {i2=3; x2=i8; i3=i9; goto spelldone;}
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=2; //arrow
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
goto spelldone;
}//magic arrow
if (CASTSPELL_SPELLTYPE==((5<<4)+0)){ //charm //txtset(spellname[(5<<4)+0],"Charm"); spellreagent[(5<<4)+0]=BLAC|NIGH|SPID; //level 6
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
if (crt->al==1){
x3=rnd*(128+(tnpc->i*2)); if (x3>255) x3=255;
if (x3==0) {i2=3; goto spelldone;}
i2=1;
crt->al=4;
crt->target=NULL;
crt->flags|=32;
if (x3>crt->charm) crt->charm=x3;
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}//al==1
}//crt
}//myobj2
goto spelldone;
}//charm
if (CASTSPELL_SPELLTYPE==((7<<4)+2)){ //mass charm //txtset(spellname[(7<<4)+2],"MassCharm"); spellreagent[(7<<4)+2]=BLAC|NIGH|SPID|MAND;
i2=2;
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
i2=1;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto masscharmblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
if (crt->al==1){
x3=rnd*(128+(tnpc->i*2)); if (x3>255) x3=255;
if (x3){
crt->al=4;
crt->target=NULL;
crt->flags|=32;
if (x3>crt->charm) crt->charm=x3;
}//x3
}//al==1
}//crt
}//myobj2
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
masscharmblocked:;
}}}//4,x,y
goto spelldone;
}//mass charm
if (CASTSPELL_SPELLTYPE==((0<<4)+5)){ //harm //txtset(spellname[(0<<4)+5],"Harm"); spellreagent[(0<<4)+5]=NIGH|SPID;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(24+(tnpc->i>>1)); //32
if (x2==0) {i2=3; x2=i8; i3=i9; goto spelldone;}
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=14; //blue ball
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
spellattcrt=TRUE; goto spellattcrt0;
//return branch for varied spells
spellattcrt1: i2=1; x2=i8; i3=i9; //<-
if (CASTSPELL_SPELLTYPE==((4<<4)+1)) goto explosion_spelldone;
if (CASTSPELL_SPELLTYPE==((7<<4)+3)) goto masskill_spelldone;
if (CASTSPELL_SPELLTYPE==((5<<4)+3)) goto flamewind_spelldone;
if (CASTSPELL_SPELLTYPE==((6<<4)+2)) goto energywind_spelldone;
if (CASTSPELL_SPELLTYPE==((7<<4)+0)) goto deathwind_spelldone;
if (CASTSPELL_SPELLTYPE==((6<<4)+0)) goto chainbolt_spelldone;
if (CASTSPELL_SPELLTYPE==((7<<4)+8)) goto tremor_spelldone;
if (CASTSPELL_SPELLTYPE==65535) goto explosion_spelldone2;
//NEWCODE
if (CASTSPELL_SPELLTYPE==((5<<4)+4)) goto hailstorm_spelldone;
//NEWCODEEND
}//crt
}//myobj2
goto spelldone;
}//harm
if (CASTSPELL_SPELLTYPE==((7<<4)+7)){ //time stop //txtset(spellname[(7<<4)+7],"TimeStop"); spellreagent[(7<<4)+7]=MAND|GARL|BLOO;
//creates a localized vortex, strongest at the centre
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x3=rnd*(64+tnpc->i);
if (x3==0) {i2=3; goto spelldone;}
for (spellx=-32;spellx<=32;spellx++){ for (spelly=-32;spelly<=32;spelly++){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto timestopblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
f=(float)x3/32.0f;
if (abs(spellx)>abs(spelly)) f2=abs(spellx); else f2=abs(spelly);
crt->wait+=((float)x3-f2*f); crt->flags|=8; //1=poison, 2=invisible, 4=asleep, 8=paralyzed
i9=SFnew(myobj2->x,myobj2->y);
sf[i9].type=1; //attack
sf[i9].x2=0;
sf[i9].x=myobj2->x;
sf[i9].y=myobj2->y;
sf[i9].wait=0.125f; //NULL
sf[i9].more=1;
}//crt
}//myobj2
timestopblocked:;
}}//spellx,spelly
i2=1;
goto spelldone;
}//time stop
if (CASTSPELL_SPELLTYPE==((1<<4)+4)){ //sleep //txtset(spellname[(1<<4)+4],"Sleep"); spellreagent[(1<<4)+4]=NIGH|SPID|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
x3=rnd*(32+(tnpc->i>>1));
if (x3==0) {i2=3; goto spelldone;}
i2=1;
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=20; //pink ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
//immune to sleep?
x4=myobj2->type&1023;
if (x4==364) goto spelldone; //acid slug
if (x4==427) goto spelldone; //ant
if (x4==357) goto spelldone; //corpser
if (x4==367) goto spelldone; //daemon
if (x4==362) goto spelldone; //winged garg
if (x4==363) goto spelldone; //garg
if (x4==355) goto spelldone; //gazer
if (x4==352) goto spelldone; //ghost
if (x4==374) goto spelldone; //hydra
if (x4==343) goto spelldone; //insects
if (x4==347) goto spelldone; //reaper
if (x4==360) goto spelldone; //rotworms
if (x4==426) goto spelldone; //scorpion
if (x4==368) goto spelldone; //skeleton
if (x4==375) goto spelldone; //slime
if (x4==345) goto spelldone; //squid
if (x4==365) goto spelldone; //tanglevine
if (x4==373) goto spelldone; //wisp
//NOTE: sleep uses a paralyze effect, but to identify the difference visually (sleeping body) asleep flag is set
crt->wait+=x3; crt->flags|=(4+8); //1=poison, 2=invisible, 4=asleep, 8=paralyzed
i9=SFnew(myobj2->x,myobj2->y);
sf[i9].type=1; //attack
sf[i9].x2=0;
sf[i9].x=myobj2->x;
sf[i9].y=myobj2->y;
sf[i9].wait=0.125f; //NULL
sf[i9].more=1;
}//crt
}//myobj2
goto spelldone;
}//sleep
if (CASTSPELL_SPELLTYPE==((4<<4)+5)){ //paralyze //txtset(spellname[(4<<4)+5],"Paralyze"); spellreagent[(4<<4)+5]=SPID|SULF|NIGH|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
x3=rnd*(32+(tnpc->i>>1));
if (x3==0) {i2=3; goto spelldone;}
crt->wait+=x3; crt->flags|=8; //1=poison, 2=invisible, 4=asleep, 8=paralyzed
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
i9=SFnew(myobj2->x,myobj2->y);
sf[i9].type=1; //attack
sf[i9].x2=0;
sf[i9].x=myobj2->x;
sf[i9].y=myobj2->y;
sf[i9].wait=0.125f; //NULL
sf[i9].more=1;
i2=1;
}//crt
}//myobj2
goto spelldone;
}//paralyze
if (CASTSPELL_SPELLTYPE==((1<<4)+2)){ //poison //txtset(spellname[(1<<4)+2],"Poison"); spellreagent[(1<<4)+2]=NIGH|BLOO|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x3=rnd*(8+5*2);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
crt->flags|=1;
i3=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i3].type=18; //green ball
sf[i3].x=myobj->x;
sf[i3].y=myobj->y;
sf[i3].x2=myobj2->x;
sf[i3].y2=myobj2->y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=0;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
x2=0; spellattcrt=TRUE; goto spellattcrt0;
}else{i2=3;}//spell failed
}//crt
}//myobj2
goto spelldone;
}//poison
if (CASTSPELL_SPELLTYPE==((2<<4)+8)){ //PROTECTION //txtset(spellname[(2<<4)+8],"Protection"); spellreagent[(2<<4)+8]=SULF|GINS|GARL;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(32+(tnpc->i>>1)); //int can only double spell effectiveness!
if (x3){
if (x3>255) x3=255; //cap
if (x3>tnpc2->protection) {tnpc2->protection=x3; tnpc->upflags|=64;}
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
i2=1;
}
if (x3==0) i2=3;
}//player
}//npc
}//myobj2
goto spelldone;
}//protection
if (CASTSPELL_SPELLTYPE==((4<<4)+9)){ //xray //txtset(spellname[(4<<4)+9],"X-ray"); spellreagent[(4<<4)+9]=MAND|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(8+(tnpc->i>>3)); //int can only double spell effectiveness!
if (x3){
if (x3>255) x3=255; //cap
if (x3>tnpc2->player->xray){
tnpc2->player->xray=x3;
//send xray update message
txtset(t,"??"); t->d2[0]=33; t->d2[1]=tnpc2->player->xray; NET_send(NETplayer,tnpc2->player->net,t);
}
i2=1;
}
if (x3==0) i2=3;
}//player
}//npc
}//myobj2
goto spelldone;
}//xray
if (CASTSPELL_SPELLTYPE==((5<<4)+5)){ //mass protect //txtset(spellname[(5<<4)+5],"MassProtect"); spellreagent[(5<<4)+5]=SULF|GINS|GARL|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x3=rnd*(32+(tnpc->i>>1)); //int can only double spell effectiveness!
if (x3){
if (x3>255) x3=255; //cap
i2=1;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto massprotectblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
if (x3>tnpc2->protection) {tnpc2->protection=x3; tnpc->upflags|=64;}
}//player
}//npc
}//myobj2
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
massprotectblocked:;
}//4
}}//spellx,spelly
}else{i2=3;} //failed
goto spelldone;
}//mass protect
if (CASTSPELL_SPELLTYPE==((6<<4)+7)){ //mass invis //txtset(spellname[(6<<4)+7],"MassInvisibility"); spellreagent[(6<<4)+7]=MAND|NIGH|BLOO|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x3=rnd*(32+(tnpc->i>>1)); //int can only double spell effectiveness!
if (x3){
if (x3>255) x3=255; //cap
i2=1;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto invisibilityblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
if (x3>tnpc2->invisibility) tnpc2->invisibility=x3;
}//player
}//npc
}//myobj2
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=19; //blue bolt
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
invisibilityblocked:;
}//4
}}//spellx,spelly
}else{i2=3;} //failed
goto spelldone;
}//mass invis
if (CASTSPELL_SPELLTYPE==((4<<4)+3)){ //invis //txtset(spellname[(4<<4)+3],"Invisibility"); spellreagent[(4<<4)+3]=NIGH|BLOO;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(32+(tnpc->i>>1)); //int can only double spell effectiveness!
if (x3){
if (x3>255) x3=255; //cap
if (x3>tnpc2->invisibility) tnpc2->invisibility=x3;
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=19; //blue bolt
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
i2=1;
}
if (x3==0) i2=3;
}//player
}//npc
}//myobj2
goto spelldone;
}//invis
if (CASTSPELL_SPELLTYPE==((2<<4)+3)){ //great light //txtset(spellname[(2<<4)+3],"GreatLight"); spellreagent[(2<<4)+3]=SULF|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(64+tnpc->i); //int can only double spell effectiveness!
if (x3){
x4=1+x3; if (x4>255) x4=255; //cap
tnpc2->light=x4;
i2=1;
}
if (x3==0) i2=3;
}//player
}//npc
}//myobj2
goto spelldone;
}//great light
if (CASTSPELL_SPELLTYPE==((0<<4)+9)){ //light //txtset(spellname[(0<<4)+9],"Light"); spellreagent[(0<<4)+9]=SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(16+(tnpc->i>>2)); //int can only double spell effectiveness!
if (x3){
x4=1+x3; if (x4>255) x4=255; //cap
tnpc2->light=x4;
i2=1;
}
if (x3==0) i2=3;
}//player
}//npc
}//myobj2
goto spelldone;
}//light
if (CASTSPELL_SPELLTYPE==((0<<4)+7)){ //awaken //txtset(spellname[(0<<4)+7],"Awaken"); spellreagent[(0<<4)+7]=GINS|GARL;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player==NULL){
if (tnpc2->schedule_last==0x91){
if (((tpx+x)==568)&&((tpy+y)==364)) goto spelldone;
if (((tpx+x)==570)&&((tpy+y)==364)) goto spelldone;
if (((tpx+x)==572)&&((tpy+y)==364)) goto spelldone;
if (((tpx+x)==574)&&((tpy+y)==364)) goto spelldone;
i2=1;
x3=rnd*(8+5*1);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success //set npc schedule to unknown! and make them just stand there
tnpc2->schedule_i=-1;
tnpc2->schedule_last=0;
tnpc2->wait_walk+=64; //1mins
//NEWCODE
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
//NEWCODEEND
}else{i2=3;}//spell failed
}//sleeping
}//!player
if (tnpc2->player){
if (tnpc2->flags&4){
i2=1;
x3=rnd*(8+5*1);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
tnpc2->flags-=4; tnpc2->wait_disable=0;
//NEWCODE
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
//NEWCODEEND
}else{i2=3;}//spell failed
}//4, sleeping
}//player
}//npc
}//myobj2
goto spelldone;
}//awaken
if (CASTSPELL_SPELLTYPE==((7<<4)+6)){ //summon //txtset(spellname[(7<<4)+6],"Summon"); spellreagent[(7<<4)+6]=MAND|GARL|BLOO;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
spellx=tpx+x; spelly=tpy+y;
if ((spellx<0)||(spellx>2047)||(spelly<0)||(spelly>1023)) goto summonfail;
if (((bt[spelly][spellx]>>10)&1)==0) goto summonfail; //land passable
if (od[spelly][spellx]) goto summonfail;
x3=rnd*(8+5*8); //int can only double spell effectiveness!
x4=rnd*(tnpc->i+10);
if (x4>=x3){//success
i2=1;
myobj2=OBJnew();
myobj2->type=367; //daemon!
myobj2->more=malloc(sizeof(creature));
ZeroMemory(myobj2->more,sizeof(creature));
crt=(creature*)myobj2->more;
crt->crt_struct=TRUE;
crt->hp=(obji[sprlnk[myobj2->type&1023]].v8>>8)*4;
crt->mp=rnd*9;
crt->al=1; x3=rnd*4; //25% chance of evil allegiance!
if (x3) crt->al=4;
crt->respawn_x=1024; //seconds till spawned crt will disappear
myobj9=OBJnew(); myobj9->type=188; crt->items=myobj9; //(not included)bag
myobj2->info|=4; //<-crt
OBJadd(spellx,spelly,myobj2);
}else{i2=3;}//spell failed
summonfail:
goto spelldone;
}//summon
if (CASTSPELL_SPELLTYPE==((7<<4)+5)){ //slime //txtset(spellname[(7<<4)+5],"Slime"); spellreagent[(7<<4)+5]=BLOO|NIGH|MAND;
i2=2;
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto slimeblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if ((myobj2->info&8)==0){ //no redirector
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
if (crt->al==1){
if (((tpx+x+spellx)<0)||((tpx+x+spellx)>2047)||((tpy+y+spelly)<0)||((tpy+y+spelly)>1023)) goto slimefail;
if ((btflags[bt[tpy+y+spelly][tpx+x+spellx]&1023]&1)==0) goto slimefail; //land passable
if ((myobj2->type&1023)==366) goto slimefail; //invincible tanglevine tendril!
if ((myobj2->type&1023)==430) if (crt->flags&128) goto slimefail;//invincible horse
x3=rnd*(640+tnpc->i*10); //128 better than kill spell!
x4=rnd*(640+tnpc->i*10);
x3=((x3+x4)>>1);
if (x3>=crt->hp){//success
i2=1;
//kill/remove creature
x3=x2;
myobj4=(object*)crt->items->more; //will point to first item
dropgoldmore3:
if (myobj4){
myobj5=(object*)myobj4->next;
OBJremove(myobj4);
if (myobj5) {myobj4=myobj5; goto dropgoldmore3;}
}
crtrespawn(myobj2);
x2=x3;
myobj2=OBJnew();
myobj2->type=375; //slime
myobj2->more=malloc(sizeof(creature));
ZeroMemory(myobj2->more,sizeof(creature));
crt=(creature*)myobj2->more;
crt->crt_struct=TRUE;
crt->hp=(obji[sprlnk[myobj2->type&1023]].v8>>8)*4;
crt->mp=rnd*9;
crt->al=1;
crt->respawn_x=1024; //seconds till spawned crt will disappear
myobj9=OBJnew(); myobj9->type=188; crt->items=myobj9; //(not included)bag
myobj2->info|=4; //<-crt
myobj2->info|=(3<<9); //slime divide!
OBJadd(tpx+x+spellx,tpy+y+spelly,myobj2);
}else{
if (i2==2) i2=3; //spell failed
}
}//al==1
}}}//myobj2
slimefail:;
slimeblocked:;
}}}//4,x,y
goto spelldone;
}//slime
if (CASTSPELL_SPELLTYPE==((3<<4)+1)){ //conjure //txtset(spellname[(3<<4)+1],"Conjure"); spellreagent[(3<<4)+1]=SPID|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
spellx=tpx+x; spelly=tpy+y;
if ((spellx<0)||(spellx>2047)||(spelly<0)||(spelly>1023)) goto conjfail;
if (((bt[spelly][spellx]>>10)&1)==0) goto conjfail; //land passable
if (od[spelly][spellx]) goto conjfail;
x3=rnd*(8+5*4); //int can only double spell effectiveness!
x4=rnd*(tnpc->i+10);
if (x4>=x3){//success
i2=1;
myobj2=OBJnew();
x3=rnd*5;
myobj2->type=342; //rat
if (x3==1) myobj2->type=358; //snake
if (x3==2) myobj2->type=344; //bat
if (x3==3) myobj2->type=371; //troll
if (x3==4) myobj2->type=361; //spider
myobj2->more=malloc(sizeof(creature));
ZeroMemory(myobj2->more,sizeof(creature));
crt=(creature*)myobj2->more;
crt->crt_struct=TRUE;
crt->hp=(obji[sprlnk[myobj2->type&1023]].v8>>8)*4;
crt->mp=rnd*9;
crt->al=4;
crt->respawn_x=1024; //seconds till spawned crt will disappear
myobj9=OBJnew(); myobj9->type=188; crt->items=myobj9; //(not included)bag
myobj2->info|=4; //<-crt
OBJadd(spellx,spelly,myobj2);
}else{i2=3;}//spell failed
conjfail:
goto spelldone;
}//conjure
if (CASTSPELL_SPELLTYPE==((4<<4)+2)){ //insect swarm //txtset(spellname[(4<<4)+2],"InsectSwarm"); spellreagent[(4<<4)+2]=BLOO|SPID|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x3=rnd*(4+(tnpc->i/16)); //int can only double spell effectiveness!
if (x3==0) {i2=3; goto spelldone;}
for (x4=1;x4<=x3;x4++){
x5=16;
isretry: spellx=tpx+x+rnd*5-2; spelly=tpy+y+rnd*5-2;
x5--;
if (x5){
if ((spellx<0)||(spellx>2047)||(spelly<0)||(spelly>1023)) goto isretry;
if (((bt[spelly][spellx]>>10)&(1+2+4))==0) goto isretry; //land, air OR sea passable
if (od[spelly][spellx]) goto isretry;
if (stormcloakcheck2(spellx,spelly,tplayer)) goto isretry;
myobj2=OBJnew();
myobj2->type=343; //insects
myobj2->more=malloc(sizeof(creature));
ZeroMemory(myobj2->more,sizeof(creature));
crt=(creature*)myobj2->more;
crt->crt_struct=TRUE;
crt->hp=(obji[sprlnk[myobj2->type&1023]].v8>>8)*4;
crt->mp=rnd*9;
crt->al=4;
crt->respawn_x=1024; //seconds till spawned crt will disappear
myobj9=OBJnew(); myobj9->type=188; crt->items=myobj9; //(not included)bag
myobj2->info|=4; //<-crt
OBJadd(spellx,spelly,myobj2);
}//x5
}//x4
i2=1;
goto spelldone;
}//insect swarm
if (CASTSPELL_SPELLTYPE==((5<<4)+8)){ //replicate //txtset(spellname[(5<<4)+8],"Replicate"); spellreagent[(5<<4)+8]=SULF|SPID|BLOO|GINS|NIGH;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
//COST OF SPELL IS reagents=8 gold, 50% fail rate ->16gold per cast!
if (myobj2=OBJfindlast(tpx+x,tpy+y)){
if (myobj2->info&256) goto cantreplicate; //quest item
if (obji[sprlnk[myobj2->type&1023]].weight==0) goto cantreplicate; //no weight!
if (obji[sprlnk[myobj2->type&1023]+(myobj2->type>>10)].v1) goto cantreplicate; //v1 (damage)
if (obji[sprlnk[myobj2->type&1023]+(myobj2->type>>10)].v2) goto cantreplicate; //v2 (armour)
if (obji[sprlnk[myobj2->type&1023]+(myobj2->type>>10)].flags&127) goto cantreplicate; //can be equipped
if (obji[sprlnk[myobj2->type&1023]].flags&1024) goto cantreplicate; //container
//EXCEPTIONS!
if ((myobj2->type&1023)==87) goto cantreplicate; //orb of the moons(kals)
if (myobj2->type==(223+1024)) goto cantreplicate; //lit powderkeg
if ((myobj2->type&1023)==414) goto cantreplicate; //skiff
if ((myobj2->type&1023)==149) goto cantreplicate; //deed
if ((myobj2->type&1023)==275) goto cantreplicate; //potion
if ((myobj2->type&1023)==58) goto cantreplicate; //spell
if ((myobj2->type&1023)==64) goto cantreplicate; //key
if ((myobj2->type&1023)==151) goto cantreplicate; //book
if ((myobj2->type&1023)==152) goto cantreplicate; //scroll
if ((myobj2->type&1023)==77) goto cantreplicate; //gem
if ((myobj2->type&1023)==93) goto cantreplicate; //sextant
if ((myobj2->type&1023)>=342) goto cantreplicate; //giant rat->horse
//***THE ABOVE LINE NEGATES ALL OBJECTS ABOVE TYPE 342, THIS HAS BEEN LEFT AS IS TO AVOID MISTAKES WHEN ADDING NEW ITEMS LATER***
if (myobj2->type==448) goto cantreplicate;//horse papers
//PENDING quest items
if ((myobj2->type&1023)==61) goto cantreplicate; //book of circles
if ((myobj2->type&1023)==212) goto cantreplicate; //fan
if ((myobj2->type&1023)==277) goto cantreplicate; //yew board (***possibly not a quest item)
//find safe location for replicated object!
x3=tpx+x; x4=tpy+y; x3++;
if (myobj3=OBJfindlast(x3,x4)){
if (obji[sprlnk[myobj3->type&1023]+(myobj3->type>>10)].flags&512) goto gotreploc;
}
if (bt[x4][x3]&1024) goto gotreploc;
x3=tpx+x; x4=tpy+y; x3--;
if (myobj3=OBJfindlast(x3,x4)){
if (obji[sprlnk[myobj3->type&1023]+(myobj3->type>>10)].flags&512) goto gotreploc;
}
if (bt[x4][x3]&1024) goto gotreploc;
x3=tpx+x; x4=tpy+y; x4++;
if (myobj3=OBJfindlast(x3,x4)){
if (obji[sprlnk[myobj3->type&1023]+(myobj3->type>>10)].flags&512) goto gotreploc;
}
if (bt[x4][x3]&1024) goto gotreploc;
x3=tpx+x; x4=tpy+y; x4--;
if (myobj3=OBJfindlast(x3,x4)){
if (obji[sprlnk[myobj3->type&1023]+(myobj3->type>>10)].flags&512) goto gotreploc;
}
if (bt[x4][x3]&1024) goto gotreploc;
x3=tpx+x; x4=tpy+y;
if (myobj3=OBJfindlast(x3,x4)){
if (obji[sprlnk[myobj3->type&1023]+(myobj3->type>>10)].flags&512) goto gotreploc;
}
if (bt[x4][x3]&1024) goto gotreploc;
goto cantreplicate; //no space!
gotreploc:
spellx=rnd*(8+5*6);
spelly=rnd*(tnpc->i+1);
if (spelly>=spellx){//success
i2=1;
myobj3=OBJnew();
myobj3->type=myobj2->type;
myobj3->info=myobj2->info;
myobj3->more2=myobj2->more2;
if (obji[sprlnk[myobj2->type&1023]+(myobj2->type>>10)].flags&4096) myobj3->more2=1;
myobj3->info|=112; //set flags as temp OBJ
if (myobj3->info&128) myobj3->info-=128; //remove stealing flag!
OBJadd(x3,x4,myobj3);
}else{
i2=3;
}
}//myobj2
cantreplicate:
goto spelldone;
}//replicate
if (CASTSPELL_SPELLTYPE==((6<<4)+4)){ //gate travel txtset(spellname[(6<<4)+4],"GateTravel"); spellreagent[(6<<4)+4]=SULF|BLAC|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
if (od[tpy+y][tpx+x]) goto gatetravel_cantcreate;
if ((bt[tpy+y][tpx+x]&1024)==0) goto gatetravel_cantcreate;
i2=1;
x3=rnd*(8+5*7);
x4=rnd*(tnpc->i+100);
if (x4>=x3){//success
myobj2=OBJnew();
myobj2->type=84+1024;
myobj2->info=3<<4; //set flags as temp OBJ
OBJadd(tpx+x,tpy+y,myobj2);
myobj2=OBJnew();
myobj2->type=84;
myobj2->info=3<<4; //set flags as temp OBJ
OBJadd(tpx+x-1,tpy+y,myobj2);
}else{i2=3;}//spell failed
gatetravel_cantcreate:
goto spelldone;
}//gatetravel
if (CASTSPELL_SPELLTYPE==((1<<4)+8)){ //untrap //txtset(spellname[(1<<4)+8],"Untrap"); spellreagent[(1<<4)+8]=SULF|BLOO;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
if (myobj2=od[tpy+y][tpx+x]){
untrap_nextobj:
if (myobj2->type==173) goto untrap_trapfound;
if (myobj2->next){myobj2=(object*)myobj2->next; goto untrap_nextobj;}
}
goto spelldone; //no trap to remove!
untrap_trapfound:
i2=3;
x3=rnd*(8+5*2);
x4=rnd*(tnpc->i+1);
if (x4<x3) goto spelldone;
i2=1;
OBJremove(myobj2);
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Trap destroyed!");
NET_send(NETplayer,tplayer->net,t);
goto spelldone;
}//untrap
if (CASTSPELL_SPELLTYPE==((0<<4)+2)){ //detect trap txtset(spellname[(0<<4)+2],"DetectTrap"); spellreagent[(0<<4)+2]=NIGH|SULF;
object * caster_obj=npc_to_obj(tnpc,tplayer);
i2=spell_detect_trap(tplayer,tnpc,NULL,caster_obj->x,caster_obj->y); // Always relative to position of caster, not casting point or player
goto spelldone;
}//detect trap
if (CASTSPELL_SPELLTYPE==((0<<4)+0)){ //create food txtset(spellname[(0<<4)+0],"CreateFood"); spellreagent[(0<<4)+0]=GARL|GINS|MAND; //level 1
i2=spell_create_food(tplayer,tnpc,NULL,tpx+x,tpy+y);
goto spelldone;
}//create food
if (CASTSPELL_SPELLTYPE==((3<<4)+3)){ //fire field txtset(spellname[(3<<4)+3],"FireField"); spellreagent[(3<<4)+3]=BLAC|SULF|SPID;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
//NEWCODE
x3=0;
if (myobj2=OBJfindlast(tpx+x,tpy+y)){x3=myobj2->type&1023;}
if ((x3==317) || (x3==318) || (x3==320) || (x3==173) || (x3==53)) {goto spelldone;}
//NEWCODEEND
if (bt[tpy+y][tpx+x]&1024){
i2=1;
x3=rnd*(8+5*4);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
myobj2=OBJnew();
myobj2->type=317; //fire
myobj2->more2=tnpc->player->id;
OBJadd(tpx+x,tpy+y,myobj2);
myobj2->info+=(2<<4);
OBJcheckflags(myobj2->x,myobj2->y);
}else{i2=3;}//spell failed
}//location OK
goto spelldone;
}//fire field
if (CASTSPELL_SPELLTYPE==((4<<4)+0)){ //energy field //txtset(spellname[(4<<4)+0],"EnergyField"); spellreagent[(4<<4)+0]=MAND|SPID|BLAC; //level 5
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
//NEWCODE
x3=0;
if (myobj2=OBJfindlast(tpx+x,tpy+y)){x3=myobj2->type&1023;}
if ((x3==317) || (x3==318) || (x3==320) || (x3==173)) {goto spelldone;}
//NEWCODEEND
if (bt[tpy+y][tpx+x]&1024){
i2=1;
x3=rnd*(8+5*5);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
myobj2=OBJnew();
myobj2->type=319; //protection field
myobj2->more2=tnpc->player->id;
OBJadd(tpx+x,tpy+y,myobj2);
myobj2->info+=(2<<4);
OBJcheckflags(myobj2->x,myobj2->y);
}else{i2=3;}//spell failed
}//location OK
goto spelldone;
}//energy field
if (CASTSPELL_SPELLTYPE==((3<<4)+7)){ //poison field txtset(spellname[(3<<4)+7],"PoisonField"); spellreagent[(3<<4)+7]=NIGH|SPID|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x3=0;
if (myobj2=OBJfindlast(tpx+x,tpy+y)){x3=myobj2->type&1023;}
if ((x3==317) || (x3==318) || (x3==320) || (x3==173) || (x3==53)) {goto spelldone;}
if (bt[tpy+y][tpx+x]&1024){
i2=1;
x3=rnd*(8+5*4);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
myobj2=OBJnew();
myobj2->type=318; //poison field
myobj2->more2=tnpc->player->id;
OBJadd(tpx+x,tpy+y,myobj2);
myobj2->info+=(2<<4);
OBJcheckflags(myobj2->x,myobj2->y);
}else{i2=3;}//spell failed
}//location OK
goto spelldone;
}//poison field
if (CASTSPELL_SPELLTYPE==((2<<4)+1)){ //dispel field //txtset(spellname[(2<<4)+1],"DispelField"); spellreagent[(2<<4)+1]=BLAC|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
if (myobj2=OBJfindlast(tpx+x,tpy+y)){
x3=myobj2->type&1023;
if ((x3>=317)&&(x3<=320)){
i2=1;
x3=rnd*(8+5*3);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
OBJsave(myobj2->x,myobj2->y);
OBJremove(myobj2);
}else{i2=3;}//spell failed
}//x3
}//myobj2
goto spelldone;
}//dispel field
if (CASTSPELL_SPELLTYPE==((3<<4)+5)){ //locate //txtset(spellname[(3<<4)+5],"Locate"); spellreagent[(3<<4)+5]=NIGH;
i2=2; //implemented!
x3=rnd*(8+5*4);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
i2=1;
if (myobj->x<1024){
x4=(myobj->x+1024-304)/8; x4-=128;
y4=(myobj->y+1024-360)/8; y4-=128;
}else{
x4=((myobj->x&255)+256-76)/2; x4-=128;
y4=((myobj->y&255)+256-90)/2; y4-=128;
}
txtset(t,"?"); t->d2[0]=8;
txtnumint(t2,abs(y4)); txtadd(t,t2);
if (y4>0) txtadd(t,"'S, "); else txtadd(t,"'N, ");
txtnumint(t2,abs(x4)); txtadd(t,t2);
if (x4>0) txtadd(t,"'E"); else txtadd(t,"'W");
NET_send(NETplayer,tplayer->net,t);
}else{i2=3;}
goto spelldone;
}//locate
if (CASTSPELL_SPELLTYPE==((4<<4)+6)){ //pickpocket //txtset(spellname[(4<<4)+6],"PickPocket"); spellreagent[(4<<4)+6]=BLOO|SPID|NIGH;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more;
x5=0; x6=0;
if (myobj2->info&2){ //<-npc
x5=1; tnpc2=(npc*)myobj2->more;
}//npc
if (myobj2->info&4){ //<-crt
x5=2; crt=(creature*)myobj2->more;
}//crt
if (x5){
x3=rnd*(8+5*5);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
i2=1;
if (x5==1){ //->npc
if (tnpc2->converse==180){
if ((tplayer->GNPCflags[6]&(1<<0))==0){
tplayer->GNPCflags[6]|=(1<<0);
myobj3=OBJnew(); myobj3->type=25; myobj3->info|=256; //guild belt
i9=SFnew(myobj->x,myobj->y); //destination is more important than the source
sf[i9].type=9; //GENERIC throw object
sf[i9].x=myobj2->x;
sf[i9].y=myobj2->y;
sf[i9].x2=myobj->x;
sf[i9].y2=myobj->y;
sf[i9].more=0xFFFF;
sf[i9].wait=myobj3->type;
//add to inventory
additemroot(tnpc,myobj3);
tnpc->upflags|=32; //inv
goto spelldone;
}//global flag
}//80
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Nothing!"); NET_send(NETplayer,tplayer->net,t);
goto spelldone;
}//npc
//crt
if (myobj3=(object*)crt->items->more){
if ((myobj3->type&1023)==98){
if (myobj3->next==NULL) goto pickpocketcrtnothing;
}
pickpocketcrtnext: x3=rnd*2; if (myobj3->next&&x3){myobj3=(object*)myobj3->next; goto pickpocketcrtnext;}
if ((myobj3->type&1023)==98){
myobj3=(object*)crt->items->more;
goto pickpocketcrtnext;
}
if (myobj3->type==88){
if (myobj3->more2>32){
myobj4=OBJnew();
myobj4->type=88; myobj4->info=112;
myobj4->more2=(rnd*(myobj3->more2-1))+1;
myobj3->more2-=myobj4->more2;
myobj3=myobj4;
goto pickpocketcrtskipremove;
}
}
OBJremove(myobj3);
pickpocketcrtskipremove:
i9=SFnew(myobj->x,myobj->y); //destination is more important than the source
sf[i9].type=9; //GENERIC throw object
sf[i9].x=myobj2->x;
sf[i9].y=myobj2->y;
sf[i9].x2=myobj->x;
sf[i9].y2=myobj->y;
sf[i9].more=0xFFFF;
sf[i9].wait=myobj3->type;
//add to inventory
additemroot(tnpc,myobj3);
tnpc->upflags|=32; //inv
}else{
pickpocketcrtnothing:
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Nothing!"); NET_send(NETplayer,tplayer->net,t);
}
}else{i2=3;}//failed
}//x3
}//myobj2
goto spelldone;
}//pickpocket
if (CASTSPELL_SPELLTYPE==((0<<4)+3)){ //cure //txtset(spellname[(0<<4)+3],"Cure"); spellreagent[(0<<4)+3]=GARL|GINS;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(8+5*1);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
i2=1;
tnpc2->flags&=(65535-1); //remove poisoned flag
tnpc2->upflags|=2;
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}else{i2=3;}//success
}//player
}//npc
}//myobj2
goto spelldone;
}//cure
if (CASTSPELL_SPELLTYPE==((0<<4)+6)){ //heal
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
//perform light heal (1 to 16->32 hp)
x3=rnd*(16+(tnpc->i>>2)); //int can only double spell effectiveness!
x4=rnd*(16+(tnpc->i>>2)); //int can only double spell effectiveness!
x3=(x3+x4)>>1;
tnpc2->hp+=x3; if (tnpc2->hp>tnpc2->hp_max) tnpc2->hp=tnpc2->hp_max;
tnpc2->upflags|=2;
i2=1;
if (x3==0) i2=3;
if (x3){
i9=SFnew(myobj2->x,myobj2->y); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=myobj2->x;
sf[i9].y2=myobj2->y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
}//player
}//npc
}//myobj2
goto spelldone;
}//heal
if (CASTSPELL_SPELLTYPE==((6<<4)+1)){ //enchant //txtset(spellname[(6<<4)+1],"Enchant"); spellreagent[(6<<4)+1]=SPID|MAND|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
if (myobj2=OBJfindlast(tpx+x,tpy+y)){
if (myobj2->type==78){ //staff
if ((myobj2->more2>>16)<=20){//25 spell limit (20+5=25)
if ((myobj2->info&(7<<9))==0){//no pending enchantments
x3=rnd*(8+5*7);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
i2=1;
//allow for 5 new spells to be added
myobj2->info|=(5<<9);
txtset(t,"?"); t->d2[0]=8; txtadd(t,"The staff glows brightly!"); NET_send(NETplayer,tplayer->net,t);
txtset(t,"?"); t->d2[0]=8; txtadd(t,"To enchant this staff cast spells upon it. (You can now add up to 5 identical spells to this staff)"); NET_send(NETplayer,tplayer->net,t);
goto spelldone;
}else{i2=3; goto spelldone;}//fail
txtset(t,"?"); t->d2[0]=8; txtadd(t,"The staff already glows! To enchant this staff cast other spells upon it."); NET_send(NETplayer,tplayer->net,t);
goto spelldone;
}//no pending enchantments
txtset(t,"?"); t->d2[0]=8;
txtnumint(t2,myobj2->more2>>16); txtadd(t,t2);
txtadd(t," spells are already held within this staff! No more may be added at this time."); NET_send(NETplayer,tplayer->net,t);
goto spelldone;
}//25 spell limit
}//staff
}//myobj2
goto spelldone;
}//enchant
if (CASTSPELL_SPELLTYPE==((1<<4)+7)){ //unlockmagic
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
if (myobj2=OBJfindlast(tpx+x,tpy+y)){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //<-redirect
x3=myobj2->type&1023;
if ((x3>=OBJ_OAKEN_DOOR)&&(x3<=OBJ_STEEL_DOOR)){
if ((myobj2->type>>10)>=12){
i2=1;
x3=rnd*(8+5*2);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
myobj2->type-=(8*1024);
myobj3=(object*)myobj2->more;
myobj3->type-=(8*1024);
}else{i2=3;}//success
}//>=12
}//x3
if (myobj2->type==(OBJ_CHEST+(3*1024))){
i2=1;
x3=rnd*(8+5*2);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
OBJsave(myobj2->x,myobj2->y);
myobj2->type-=(2*1024);
}else{i2=3;}//success
}//chest
}//myobj2
goto spelldone;
}//unlock
if (CASTSPELL_SPELLTYPE==((3<<4)+9)){ //WindChange txtset(spellname[(3<<4)+9],"WindChange"); spellreagent[(3<<4)+9]=SULF|BLOO;
i2=2; //implemented!
x3=rnd*(8+5*4);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
i2=1;
x3=tplayer->windx; y3=tplayer->windy;
if ((x3==0)&&(y3==0)) {x3=windx; y3=windy;}
if ((x3==0)&&(y3==0)) {x3=0; y3=1; goto windchange_cast;}
if ((x3==0)&&(y3==1)) {x3=-1; y3=1; goto windchange_cast;}
if ((x3==-1)&&(y3==1)) {x3=-1; y3=0; goto windchange_cast;}
if ((x3==-1)&&(y3==0)) {x3=-1; y3=-1; goto windchange_cast;}
if ((x3==-1)&&(y3==-1)) {x3=0; y3=-1; goto windchange_cast;}
if ((x3==0)&&(y3==-1)) {x3=1; y3=-1; goto windchange_cast;}
if ((x3==1)&&(y3==-1)) {x3=1; y3=0; goto windchange_cast;}
if ((x3==1)&&(y3==0)) {x3=1; y3=1; goto windchange_cast;}
if ((x3==1)&&(y3==1)) {x3=0; y3=1; goto windchange_cast;}
windchange_cast:
tplayer->windx=x3; tplayer->windy=y3;
txtset(t,"??"); t->d2[0]=14; t->d2[1]=(tplayer->windx+1)+(tplayer->windy+1)*4; NET_send(NETplayer,tplayer->net,t);
}else{i2=3;}
goto spelldone;
}//WindChange
if (CASTSPELL_SPELLTYPE==((3<<4)+8)){ //sleep field txtset(spellname[(3<<4)+8],"SleepField"); spellreagent[(3<<4)+8]=GINS|SPID|BLAC;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x3=0;
if (myobj2=OBJfindlast(tpx+x,tpy+y)){x3=myobj2->type&1023;}
if ((x3==317) || (x3==318) || (x3==320) || (x3==173)) {goto spelldone;}
if (bt[tpy+y][tpx+x]&1024){
i2=1;
x3=rnd*(8+5*4);
x4=rnd*(tnpc->i+1);
if (x4>=x3){//success
myobj2=OBJnew();
myobj2->type=320; //sleep
myobj2->more2=tnpc->player->id;
OBJadd(tpx+x,tpy+y,myobj2);
myobj2->info+=(2<<4);
OBJcheckflags(myobj2->x,myobj2->y);
}else{i2=3;}//spell failed
}//location OK
goto spelldone;
}//sleep field
if (CASTSPELL_SPELLTYPE==((3<<4)+6)){ //mass cure //txtset(spellname[(3<<4)+6],"MassCure"); spellreagent[(3<<4)+6]=GARL|GINS;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
i9=SFnew(tpx+x,tpy+y); //destination is more important than the source
sf[i9].type=19; //blue bolt
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=tpx+x;
sf[i9].y2=tpy+y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
i2=1;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto masscureblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(8+5*1);
x4=rnd*(tnpc->i+10);
if (x4>=x3){//success
tnpc2->flags&=(65535-1); //remove poisoned flag
tnpc2->upflags|=2;
}
}//player
}//npc
}//myobj2
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=14; //blue ball
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
masscureblocked:;
}//4
}}//spellx,spelly
goto spelldone;
}//mass cure
if (CASTSPELL_SPELLTYPE==((2<<4)+5)){ //mass awaken //txtset(spellname[(2<<4)+5],"MassAwaken"); spellreagent[(2<<4)+5]=GINS|GARL;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
i9=SFnew(tpx+x,tpy+y); //destination is more important than the source
sf[i9].type=19; //blue bolt
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=tpx+x;
sf[i9].y2=tpy+y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
i2=1;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly);
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto massawakenblocked;
if (myobj2){
if (myobj2->info&2){ //<-npc
x3=rnd*(8+5*3);
x4=rnd*(tnpc->i+10);
if (x4>=x3){//success
tnpc2=(npc*)myobj2->more;
if (tnpc2->player==NULL){
if (tnpc2->schedule_last==0x91){
if (((tpx+x)==568)&&((tpy+y)==364)) goto massawaken_npca;
if (((tpx+x)==570)&&((tpy+y)==364)) goto massawaken_npca;
if (((tpx+x)==572)&&((tpy+y)==364)) goto massawaken_npca;
if (((tpx+x)==574)&&((tpy+y)==364)) goto massawaken_npca;
tnpc2->schedule_i=-1;
tnpc2->schedule_last=0;
tnpc2->wait_walk+=64; //1mins
}//sleeping
}//!player
if (tnpc2->player){
if (tnpc2->flags&4){
tnpc2->flags-=4; tnpc2->wait_disable=0;
}//4, sleeping
}//player
}//fail
}//npc
}//myobj2
massawaken_npca:
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=14+4*256; //blue ball
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
massawakenblocked:;
}//4
}}//spellx,spelly
goto spelldone;
}//mass awaken
if (CASTSPELL_SPELLTYPE==((2<<4)+6)){ //mass sleep //txtset(spellname[(2<<4)+6],"MassSleep"); spellreagent[(2<<4)+6]=GINS|NIGH|SPID;
i2=2;
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
i9=SFnew(tpx+x,tpy+y); //destination is more important than the source
sf[i9].type=19; //blue bolt
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=tpx+x;
sf[i9].y2=tpy+y;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
i2=1;
for (spellx=-2;spellx<=2;spellx++){ for (spelly=-2;spelly<=2;spelly++){
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto masssleepblocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&8) myobj2=(object*)myobj2->more; //redirect
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
x3=rnd*(32+(tnpc->i>>1));
//immune to sleep?
x4=myobj2->type&1023;
if (x4==364) goto masssleep_immune; //acid slug
if (x4==427) goto masssleep_immune; //ant
if (x4==357) goto masssleep_immune; //corpser
if (x4==367) goto masssleep_immune; //daemon
if (x4==362) goto masssleep_immune; //winged garg
if (x4==363) goto masssleep_immune; //garg
if (x4==355) goto masssleep_immune; //gazer
if (x4==352) goto masssleep_immune; //ghost
if (x4==374) goto masssleep_immune; //hydra
if (x4==343) goto masssleep_immune; //insects
if (x4==347) goto masssleep_immune; //reaper
if (x4==360) goto masssleep_immune; //rotworms
if (x4==426) goto masssleep_immune; //scorpion
if (x4==368) goto masssleep_immune; //skeleton
if (x4==375) goto masssleep_immune; //slime
if (x4==345) goto masssleep_immune; //squid
if (x4==365) goto masssleep_immune; //tanglevine
if (x4==373) goto masssleep_immune; //wisp
//NOTE: sleep uses a paralyze effect, but to identify the difference visually (sleeping body) asleep flag is set
crt->wait+=x3; crt->flags|=(4+8); //1=poison, 2=invisible, 4=asleep, 8=paralyzed
i9=SFnew(myobj2->x,myobj2->y);
sf[i9].type=1; //attack
sf[i9].x2=0;
sf[i9].x=myobj2->x;
sf[i9].y=myobj2->y;
sf[i9].wait=0.125f; //NULL
sf[i9].more=1;
}//crt
}//myobj2
masssleep_immune:
if ((abs(spellx)==2)||(abs(spelly)==2)){
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=20+4*256; //pink ball
sf[i9].x=tpx+x;
sf[i9].y=tpy+y;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
}
masssleepblocked:;
}}}//4,x,y
goto spelldone;
}//mass sleep
if (CASTSPELL_SPELLTYPE==((5<<4)+6)){ //negate magic //txtset(spellname[(5<<4)+6],"NegateMagic"); spellreagent[(5<<4)+6]=GARL|MAND|SULF;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
myobj2=OBJfindlast(tpx+x,tpy+y);
if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x,tpy+y);
if (myobj2){
if (myobj2->info&2){ //<-npc
tnpc2=(npc*)myobj2->more;
if (tnpc2->player){
x3=rnd*(32+(tnpc->i>>1)); //int can only double spell effectiveness!
if (x3){
if (x3>255) x3=255; //cap
if (x3>tnpc2->negatemagic) {tnpc2->negatemagic=x3;}
i2=1;
}
if (x3==0) i2=3;
}//player
}//npc
}//myobj2
goto spelldone;
}//negate magic
if (CASTSPELL_SPELLTYPE==((5<<4)+4)){ //hail storm //txtset(spellname[(5<<4)+4],"HailStorm"); spellreagent[(5<<4)+4]=BLOO|BLAC|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x4=4;
for (x4;x4>0;x4--) {
x3=3+rnd*(1+(tnpc->i-24)/8);
for (x3;x3>0;x3--){
spellx=rnd*(9)-6;
spelly=rnd*(9)-6;
if (spellx <= -3) {spellx=rnd*(3)-1;}
if (spelly <= -3) {spelly=rnd*(3)-1;}
if ((abs(spellx)+abs(spelly))!=4){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto hailstorm_blocked;
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
i9=i3; i8=x2; //backup!
x2=rnd*(16+(tnpc->i>>1));
if (x2==0) {i2=1; x2=i8; i3=i9; goto hailstorm_spelldone;}
i3=SFnew(myobj2->x,myobj2->y);
sf[i3].type=1; //attack
sf[i3].x2=x2;
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
spellattcrt=TRUE; goto spellattcrt0;
}//crt
}//myobj2
hailstorm_spelldone:;
x5=x4/2;
i9=SFnew(tpx+x+spellx,tpy+y+spelly); //destination is more important than the source
sf[i9].type=13+x5*2*256; //sling bullet
sf[i9].x=tpx+x+spellx-2;
sf[i9].y=tpy+y+spelly-1-x4;
sf[i9].x2=tpx+x+spellx;
sf[i9].y2=tpy+y+spelly;
sf[i9].more=0xFFFF;
sf[i9].wait=1;
hailstorm_blocked:;
}//!=4
}//x3
}//x4
i2=1;
goto spelldone;
}//hail storm
if (CASTSPELL_SPELLTYPE==((0<<4)+8)){ //ignite //txtset(spellname[(0<<4)+8],"Ignite"); spellreagent[(0<<4)+8]=SULF|BLAC;
i2=spell_ignite(tplayer,tnpc,NULL,tpx+x,tpy+y);
goto spelldone;
}//ignite
if (CASTSPELL_SPELLTYPE==((0<<4)+4)){ //douse //txtset(spellname[(0<<4)+4],"Douse"); spellreagent[(0<<4)+4]=GARL|BLAC;
i2=spell_douse(tplayer,tnpc,NULL,tpx+x,tpy+y);
goto spelldone;
}//douse
if (CASTSPELL_SPELLTYPE==((4<<4)+7)){ //reveal //txtset(spellname[(4<<4)+7],"Reveal"); spellreagent[(4<<4)+7]=SPID|NIGH|MAND;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
i2=1;
x3=rnd*(8+5*5);
x4=rnd*(tnpc->i+1);
if (x4>=x3) {
i2=1;
for (spellx=-7;spellx<=7;spellx++){ for (spelly=-7;spelly<=7;spelly++){
if ((abs(spellx)+abs(spelly))<=10){
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly); if (myobj2==NULL) myobj2=OBJfindlastall(tpx+x+spellx,tpy+y+spelly);
if (myobj2){
if (myobj2->info&4){ //<-crt
crt=(creature*)myobj2->more;
if (crt->flags&2){
crt->flags-=2; //if creature invisible make visible.
}//flags
}//crt
}//myobj2
}
}} //spellx,y
}//success
else {i2=3;} //fail
}//reveal
if (CASTSPELL_SPELLTYPE==((5<<4)+9)){ //web //txtset(spellname[(5<<4)+9],"Web"); spellreagent[(5<<4)+9]=SPID;
i2=2; //implemented!
if (stormcloakcheck2(tpx+x,tpy+y,tplayer)) goto spelldone;
x3=rnd*(8+5*6);
x4=rnd*(tnpc->i+100);
if (x4>=x3){//success
i2=1;
i9=SFnew(tpx+x,tpy+y); //destination is more important than the source
sf[i9].type=9; //generic throw object
sf[i9].x=myobj->x;
sf[i9].y=myobj->y;
sf[i9].x2=tpx+x;
sf[i9].y2=tpy+y;
sf[i9].more=0xFFFF;
sf[i9].wait=53;
for (spellx=-1;spellx<=1;spellx++){ for (spelly=-1;spelly<=1;spelly++){
if (stormcloakcheck2(tpx+x+spellx,tpy+y+spelly,tplayer)) goto web_blocked;
if ((x3==317) || (x3==318) || (x3==320) || (x3==173) || (x3==53)) {goto web_blocked;}
myobj2=OBJfindlast(tpx+x+spellx,tpy+y+spelly);
if (bt[tpy+y+spelly][tpx+x+spellx]&1024) {
myobj2=OBJnew();
myobj2->type=53; //web
myobj2->more2=tnpc->player->id;
myobj2->info|=32;
//if tile has an object, place web under it
OBJtmp=od[tpy+y+spelly][tpx+x+spellx];
if (OBJtmp) {
OBJtmp->prev=myobj2;
myobj2->next=OBJtmp;
myobj2->x=tpx+x+spellx;
myobj2->y=tpy+y+spelly;
od[tpy+y+spelly][tpx+x+spellx]=myobj2;
} else {
OBJadd(tpx+x+spellx,tpy+y+spelly,myobj2);
}
}
else if (myobj2 && myobj2->info&4) {
crt=(creature*)myobj2->more;
if ((myobj2->type&1023)!=361) {
x3=rnd*(32+(tnpc->i>>1)/2);
crt->wait+=x3; crt->flags|=8; //1=poison, 2=invisible, 4=asleep, 8=paralyzed
}
myobj2=OBJnew();
myobj2->type=53; //web
myobj2->more2=tnpc->player->id;
myobj2->info|=112; //set flags as temp OBJ
//if tile has an object, place web under it
OBJtmp=od[tpy+y+spelly][tpx+x+spellx];
if (OBJtmp) {
OBJtmp->prev=myobj2;
myobj2->next=OBJtmp;
od[tpy+y+spelly][tpx+x+spellx]=myobj2;
} else {
OBJadd(tpx+x+spellx,tpy+y+spelly,myobj2);
}
}//location OK
web_blocked:;
}}//spellx,spelly
}else{i2=3;}//spell failed
}//web
//NEWCODEEND
spelldone:
if (i2==0){ //not implemented!
txtset(t,"?"); t->d2[0]=8; txtadd(t,"U6O can't cast this spell yet!"); NET_send(NETplayer,tplayer->net,t);
}
//4. display words of power if spell was a success
//5. remove mp&reagents if successful
if ((i2==1)||(i2==3)){
if (!staff_cast_spell){
//subtract mp
tnpc->mp-=((CASTSPELL_SPELLTYPE>>4)+1);
tnpc->upflags|=4;
//remove reagents
x4=spellreagent[CASTSPELL_SPELLTYPE];
for(x2=0;x2<CASTSPELL_ENUMERATEDINVENTORYOBJS;x2++){
x3=OBJlist_list[x2]->type; //gpf
if ((x3>=65)&&(x3<=72)){
x3-=65;
if (x4&(1<<x3)){
x4-=(1<<x3);
OBJlist_list[x2]->more2--;
if (OBJlist_list[x2]->more2==0) OBJremove(OBJlist_list[x2]);
}//x4
}//x3
}//x2
tnpc->upflags|=32;
}//!staff_cast_spell
spelldone_donttakereagents:
if (staff_cast_spell){
x3=tplayer->staffcast_staff->more2>>16;
x3--;
if (x3){
tplayer->staffcast_staff->more2&=65535;
tplayer->staffcast_staff->more2|=(x3<<16);
}else tplayer->staffcast_staff->more2=0; //all spells used, revert to unclassified staff
}
//spell delay
tnpc->wait_cast+=4.0f-((float)tnpc->i/32.0f);
//txtset(t,"??"); t->d2[0]=18; t->d2[1]=iparty; NET_send(NETplayer,tplayer->net,t); //set cast icon!
}
if (i2==2){ //invalid target
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Can't cast there!"); NET_send(NETplayer,tplayer->net,t);
}
}
if (i2==3){ //spell failed!
if (!cast_spell){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Spell failed!"); NET_send(NETplayer,tplayer->net,t);
}
}
castfailed:;
if (cast_spell){
if (cast_spell==1){ cast_spell=0; goto cast_spell1;}
if (cast_spell==2){ cast_spell=0; goto cast_spell2;}
}
goto skip_pickup;
}//i
}//mbclick
//use and other stuff
if (tplayer->mobj!=NULL){ //drop item
i=tplayer->mf;
if (i<=7){ if(tplayer->party[i]){
if (tplayer->key&KEYmbclick){
tnpc=(npc*)tplayer->party[i]->more; //*tnpc
//scroll inventory down
if ((tplayer->mx>=(111-3))&&(tplayer->my>=(228-3))){
if ((tplayer->mx<=(121+3))&&(tplayer->my<=(243+3))){
tnpc->upflags|=32;
//is scroll down available?
myobj=(object*)tnpc->baseitem;
myobj=(object*)myobj->more;
x=61; y=61; x3=tnpc->baseitem_offset;
dniz2:
if (myobj!=NULL){
if (x3>0) {x3--;goto skipbio1z2;}
x=x+16;
if (x>109) {x=61;y=y+16;}
if (y>109){
if (myobj->next!=NULL)
{
tnpc->baseitem_offset+=4;
}
goto diskipz2;
}
if (myobj->next!=NULL){
skipbio1z2:
myobj=(object*)myobj->next;
goto dniz2;
}
}
diskipz2:;
goto skip_pickup;
}}
//scroll inventory up
if ((tplayer->mx>=(111-3))&&(tplayer->my>=(197-3))){ if ((tplayer->mx<=(121+3))&&(tplayer->my<=(212+3))){
if (tnpc->baseitem_offset>=4) {tnpc->baseitem_offset-=4;}else{tnpc->baseitem_offset=0;}
tnpc->upflags|=32;
goto skip_pickup;
}}
//clicked on opened "bag" icon ->close bag
if ((tplayer->mx>=(90))&&(tplayer->my>=(128+3))&&(tplayer->mx<((90)+32))&&(tplayer->my<((128+3)+32))){
if (tnpc->baseitem!=tnpc->items){ //backwards traverse
myobj2=tnpc->baseitem;
myobj=(object*)tnpc->baseitem->prev;
getprev9:
if ((myobj->more!=myobj2)||((obji[sprlnk[myobj->type&1023]].flags&1024)==0)) {myobj2=myobj; myobj=(object*)myobj->prev; goto getprev9;}
tnpc->baseitem=myobj;
tnpc->baseitem_offset=0;
tnpc->upflags|=32;
goto skip_pickup;
}//tnpc->baseitem!=tnpc->items
}//x,y
if (tplayer->action==2){ //look, opens inventory container items 2004
tnpc->upflags|=32;
if ((tplayer->mx>=122)&&(tplayer->my>=122)){
x=(tplayer->mx-122)/32;
y=(tplayer->my-122)/32;
i2=x+(y*4);
myobj=tnpc->baseitem;
myobj=(object*)myobj->more;
i3=tnpc->baseitem_offset;
fo2c:
if (i3>0){i3--;myobj=(object*)myobj->next;goto fo2c;}
if (myobj!=NULL){
if (i2>0){
if (myobj->next!=NULL){
myobj=(object*)myobj->next;
i2--;
goto fo2c;
}else{myobj=NULL;}
}
}
if (myobj!=NULL){
if ((myobj->type==(OBJ_CHEST+1024*2))||(myobj->type==(OBJ_CHEST+1024*3))) goto inventory_look; //magically/locked chests
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_body[i3]==myobj){
goto inventory_look; //block looking inside resurrectable bodies
}}}
if (obji[sprlnk[myobj->type&1023]].flags&1024){ //2003: check container flag
tnpc->baseitem=myobj;
tnpc->baseitem_offset=0;
goto skip_pickup;
}
goto inventory_look;
}//myobj!=NULL
goto skip_pickup;
} //if x&y
//what about equipped items?
x2=tplayer->mx; y2=tplayer->my;
x3=helmx; y3=helmy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->helm) goto inventory_look;
}
x3=wep_rightx; y3=wep_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->wep_right) goto inventory_look;
}
x3=wep_leftx; y3=wep_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->wep_left) goto inventory_look;
}
x3=armourx; y3=armoury;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->armour) goto inventory_look;
}
x3=bootsx; y3=bootsy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->boots) goto inventory_look;
}
x3=neckx; y3=necky;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->neck) goto inventory_look;
}
x3=ring_leftx; y3=ring_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->ring_left) goto inventory_look;
}
x3=ring_rightx; y3=ring_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->ring_right) goto inventory_look;
}
goto skip_pickup;
} //action==2
//tnpc->update=1;
if (tplayer->my<122) goto port_drop;
if (tplayer->mx>=122){
if (tplayer->my>=122){
port_drop:
sprite_drop:
if (tplayer->mobj->info&256) goto questitem_skipweightcheck;
//NEWCODE
if (U6O_DEBUG){
goto questitem_skipweightcheck; //for debugging
}
//NEWCODEEND
if ((tnpc->wt+WTfind(tplayer->mobj))<=tnpc->wt_max){
questitem_skipweightcheck:
if (tnpc->baseitem->type==57){
if (tplayer->mobj->type!=58){
txtset(t,"?");
t->d2[0]=8;
txtadd(t,"Only spells can go into the spellbook!");
NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
}
if (tnpc->baseitem->type==62){ //vortex cube
if ((tplayer->mobj->type&1023)!=73){
txtset(t,"?");
t->d2[0]=8;
txtadd(t,"Only moonstones can go into the vortex cube!");
NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
}
if (tplayer->mobj->info&256){ //drop quest item
if ((i!=0)||((tnpc->baseitem->info&256)==0)){
txtset(t,"?");
t->d2[0]=8;
txtadd(t,"You cannot put a quest item here!");
NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}//not primary player OR not quest bag
}
if ((tplayer->mobj->type&1023)==414){ //skiff
if (tnpc->baseitem!=tnpc->items){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a skiff in there!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
}//414
if (tplayer->mobj->type==149){ //deed
if (tnpc->baseitem!=tnpc->items){
if ((tnpc->baseitem->info&256)==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a deed in there!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
}
if (i){//not the primary player
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," cannot be given a deed!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
//if (tnpc->converse!=201){ if (tnpc->converse!=0){
//txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," cannot be given a deed!"); NET_send(NETplayer,tplayer->net,t);
//goto skip_pickup;
//}}
}//149
if (tplayer->mobj->type==448){ //horse papers
if (tnpc->baseitem!=tnpc->items){
if ((tnpc->baseitem->info&256)==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put the horse papers in there!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
}
if (i){//not the primary player
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," cannot carry horse papers!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
//if (tnpc->converse!=201){ if (tnpc->converse!=0){
//txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," cannot carry horse papers!"); NET_send(NETplayer,tplayer->net,t);
//goto skip_pickup;
//}}
}//448
//check that current container is NOT a dead monster (they are not to be used as containers)
if (((tnpc->baseitem->type&1023)>432)&&((tnpc->baseitem->type&1023)<=447)){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put items in here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
tnpc->upflags|=32; //inv
stealing(tplayer,tplayer->mobj);
myobj=tnpc->baseitem;
myobj2=(object*)myobj->more;
if (myobj2!=NULL){
//scan for multiple item
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&4096){ //multiple
myobj3=myobj2;
joinitem:
if (myobj3->type==tplayer->mobj->type){ //same type
if ((tplayer->mobj->info&128)==(myobj3->info&128)){
if (((myobj3->type&1023)==90)&&(myobj3->info!=tplayer->mobj->info)) goto cantjoin; //cant join half burnt torches
myobj3->more2+=tplayer->mobj->more2;
OBJrelease(tplayer->mobj);
tplayer->mobj=NULL;
goto joinitem_finished;
}//same stealing type
}//same type
if (myobj3->next) {myobj3=(object*)myobj3->next; goto joinitem;}
}//4096
cantjoin:
//if (obji[sprlnk[myobj2->type&1023]+(myobj2->type>>10)].flags&4096){
//scan inventory list and append object if possible
//}else{
tplayer->mobj->next=myobj2;
myobj2->prev=tplayer->mobj;
tplayer->mobj->prev=myobj;
myobj->more=tplayer->mobj;
tplayer->mobj=NULL; //clear selected mouse object
//}
}else{
tplayer->mobj->next=NULL;
tplayer->mobj->prev=myobj;
myobj->more=tplayer->mobj;
tplayer->mobj=NULL; //clear selected mouse object
}
joinitem_finished:;
} //weight
goto skip_pickup; //mobj may have been set to 0!
}}//mx,my
//quest_skipdrop:
//drop equip item
//2003: no switching
x2=tplayer->mx; y2=tplayer->my;
//NEWCODE
if (U6O_DEBUG){
goto debug_skipweightcheck; //for debugging
}
if ((tnpc->wt+WTfind(tplayer->mobj))<=tnpc->wt_max){
debug_skipweightcheck:;
//NEWCODEEND
x3=helmx; y3=helmy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->helm==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&1){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
tnpc->helm=tplayer->mobj;
tplayer->mobj=NULL;
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
x3=wep_rightx; y3=wep_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->wep_right==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&(8+16)){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tnpc->wep_left!=NULL){
if (obji[sprlnk[tnpc->wep_left->type&1023]+(tnpc->wep_left->type>>10)].flags&16) goto skip_pickup;
}
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&16){ //2 handed
if (tnpc->wep_left!=NULL) goto skip_pickup;
}
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
if ((tplayer->mobj->type&1023)==83){ //oil flask
if (tplayer->mobj->more2>1){ //seperate item
myobj9=OBJnew();
myobj9->type=83;
myobj9->more2=tplayer->mobj->more2-1;
tplayer->mobj->more2=1;
tnpc->wep_right=tplayer->mobj;
tplayer->mobj=myobj9;
goto wep_right_skip;
}//>1
}//83
if ((tplayer->mobj->type&1023)==90){ //torch
//tnpc->light=1;
tplayer->mobj->type=90+1024;
if (tplayer->mobj->more2>1){ //seperate item
myobj9=OBJnew();
myobj9->type=90;
myobj9->more2=tplayer->mobj->more2-1;
tplayer->mobj->more2=1;
tnpc->wep_right=tplayer->mobj;
tplayer->mobj=myobj9;
goto wep_right_skip;
}//>1
}//90
if (tplayer->mobj->type==57){ //ready spellbook
tnpc->upflags|=128;
}
tnpc->wep_right=tplayer->mobj;
tplayer->mobj=NULL;
wep_right_skip:
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
x3=wep_leftx; y3=wep_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->wep_left==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&(8+16)){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tnpc->wep_right!=NULL){
if (obji[sprlnk[tnpc->wep_right->type&1023]+(tnpc->wep_right->type>>10)].flags&16) goto skip_pickup;
}
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&16){ //2 handed
if (tnpc->wep_right!=NULL) goto skip_pickup;
}
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
if ((tplayer->mobj->type&1023)==83){ //oil flask
if (tplayer->mobj->more2>1){ //seperate item
myobj9=OBJnew();
myobj9->type=83;
myobj9->more2=tplayer->mobj->more2-1;
tplayer->mobj->more2=1;
tnpc->wep_left=tplayer->mobj;
tplayer->mobj=myobj9;
goto wep_left_skip;
}//>1
}//83
if ((tplayer->mobj->type&1023)==90){ //torch
//tnpc->light=1;
tplayer->mobj->type=90+1024;
if (tplayer->mobj->more2>1){ //seperate item
myobj9=OBJnew();
myobj9->type=90;
myobj9->more2=tplayer->mobj->more2-1;
tplayer->mobj->more2=1;
tnpc->wep_left=tplayer->mobj;
tplayer->mobj=myobj9;
goto wep_left_skip;
}//>1
}//90
if (tplayer->mobj->type==57){ //ready spellbook
tnpc->upflags|=128;
}
tnpc->wep_left=tplayer->mobj;
tplayer->mobj=NULL;
wep_left_skip:
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
x3=armourx; y3=armoury;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->armour==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&4){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
tnpc->armour=tplayer->mobj;
tplayer->mobj=NULL;
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
x3=bootsx; y3=bootsy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->boots==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&64){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
tnpc->boots=tplayer->mobj;
tplayer->mobj=NULL;
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
x3=neckx; y3=necky;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->neck==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&2){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
tnpc->neck=tplayer->mobj;
tplayer->mobj=NULL;
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
x3=ring_leftx; y3=ring_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->ring_left==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&32){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
//if ((tplayer->mobj->type&1023)==258){ //invisibility ring (oooooh!)
//tnpc->flags|=2; //set invisibility flag
//}//258
tnpc->ring_left=tplayer->mobj;
tplayer->mobj=NULL;
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
x3=ring_rightx; y3=ring_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->ring_right==NULL){
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&32){
if ((tnpc->wt2+WTfind(tplayer->mobj))<=tnpc->wt2_max){
if (tplayer->mobj->info&256){ if (i){ //quest item->party member
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a quest item here!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}}
stealing(tplayer,tplayer->mobj);
tnpc->ring_right=tplayer->mobj;
tplayer->mobj=NULL;
tnpc->upflags|=64; //update flags
goto skip_pickup;
}}}}
}//weight check!
} //mbclick
} //valid i(mf)
} //i(mf)<=7
//drop item on primary surface
if ((tplayer->mf==255)&&(tplayer->key&KEYmbclick)){
x=tplayer->mx/32;
y=tplayer->my/32;
x+=tpx;
y+=tpy;
myobj=OBJfindlast(x,y);
if (myobj!=NULL){
i=myobj->type; i2=sprlnk[i&1023];
//i2=i>>10; //26/11/2004 removed for Sherry compatibility
if (tplayer->action==1){ //use item on item
//PROXIMITY CHECK REQUIRED HERE!
z2=1;
for (z=0;z<=7;z++){
if (myobj2=tplayer->party[z]){
if (abs(myobj2->x-myobj->x)<=1){
if (abs(myobj2->y-myobj->y)<=1){
z2=0;
}} }}
if (z2) goto skip_pickup;
if ((tplayer->mobj->type&1023)==178){ //empty bucket
if ((myobj->type&1023)==428){ //cow
tplayer->mobj->type=180; //milk bucket
tplayer->mobj_last=NULL; //->send message
goto skip_pickup;
}
if ((myobj->type&1023)==233){ //well
tplayer->mobj->type=179; //water bucket
tplayer->mobj_last=NULL; //->send message
goto skip_pickup;
}
}
if ((tplayer->mobj->type&1023)==183){ //empty jar
if ((myobj->type&1023)==182){ //beehive
if ((myobj->info&(15<<9))==0){ //empty?
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Empty!"); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}
tplayer->mobj->type=184; //jar of honey
tplayer->mobj_last=NULL; //->send message
if (myobj->info&112){ //temp object?
x2=(myobj->info>>9)&15; x2--;
myobj->info&=(0xFFFF-(15<<9));
myobj->info|=(x2<<9);
}
goto skip_pickup;
}
}
//grain on horse
if (tplayer->mobj->type==166){//grain
if ((myobj->type&1023)==431){
txtsetchar(t,8); txtadd(t,"Not now!"); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}
if ((myobj->type&1023)==430){
if (myobj->info&8) myobj=(object*)myobj->more;
if (myobj->info&4){
crt=(creature*)myobj->more;
if (crt->flags&128){
if (((crt->respawn_x>>4)&3)!=3){
crt->respawn_x|=(3<<4);
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,"You pour the grain into the horse's feed bag."); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}//!=3
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,"This horse's feed bag is already full!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}else{
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,"You feed the horse the sack of grain."); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}
}//crt
}//horse(without rider)
}//grain
//horseshoes on horse
if (tplayer->mobj->type==202){//horseshoes
if ((myobj->type&1023)==431){
txtsetchar(t,8); txtadd(t,"Not now!"); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}
if ((myobj->type&1023)==430){
if (myobj->info&8) myobj=(object*)myobj->more;
if (myobj->info&4){
crt=(creature*)myobj->more;
if (crt->flags&128){
if (((crt->respawn_x>>6)&3)!=3){
crt->respawn_x|=(3<<6);
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,"You fit a new horseshoe upon each hoof."); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}//!=3
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,"This horse is already fitted with new horseshoes!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}else{
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,"You fit the horse with new horseshoes."); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}
}//crt
}//horse(without rider)
}//horseshoes
//potions
if (tplayer->mobj->type==(275+1*1024)){ //red potion
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player){
tnpc->flags&=(65535-1); //remove poisoned flag
tnpc->upflags|=2;
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
goto skip_pickup;
}
}
}
//use fan on balloon while flying
if (tplayer->mobj->type==(212)){ //fan
if (myobj->info&2 && (myobj->type&1023)==423){ //<-NPC
//check if walking passable without balloon
i4=myobj->x; i5=myobj->y; OBJremove(myobj);
if (bt[i5][i4]&1024){
OBJadd(i4,i5,myobj);
use_craft(tplayer,myobj);
}else{
OBJadd(i4,i5,myobj);
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Not here!"); NET_send(NETplayer,tplayer->net,t);
}
goto skip_pickup;
}
}
if (tplayer->mobj->type==(275+2*1024)){ //yellow potion
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player){
tnpc->hp+=30; if (tnpc->hp>tnpc->hp_max) tnpc->hp=tnpc->hp_max;
tnpc->upflags|=2;
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
goto skip_pickup;
}
}
}
if (tplayer->mobj->type==(275+3*1024)){ //green potion
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player==tplayer){
tnpc->flags|=1; //set poisoned flag
tnpc->upflags|=2;
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
}
goto skip_pickup;
}
}
//if (tnpc->invisibility){
if (tplayer->mobj->type==(275+6*1024)){ //black potion
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player){
if (tnpc->invisibility<32) tnpc->invisibility=32;
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
goto skip_pickup;
}
}
}
if (tplayer->mobj->type==(275+5*1024)){ //purple potion
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player){
if (tnpc->protection<32) tnpc->protection=32; //~2mins
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
tnpc->upflags|=64; //update ->arm value
goto skip_pickup;
}
}
}
if (tplayer->mobj->type==(275+7*1024)){ //white potion
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player){
if (tnpc->player->xray<8){
tnpc->player->xray=8;
//send xray update message
txtset(t,"??"); t->d2[0]=33; t->d2[1]=tnpc->player->xray; NET_send(NETplayer,tnpc->player->net,t);
}
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
goto skip_pickup;
}
}
}
if (tplayer->mobj->type==(275+0*1024)){ //blue potion
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player){
if (tnpc->flags&4){ //sleep flag
tnpc->flags-=4; tnpc->wait_disable=0;
}//4
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
goto skip_pickup;
}
}
}
if (tplayer->mobj->type==(275+4*1024)){ //orange potion (sleep)
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player==tplayer){
tnpc->flags|=4; //set sleep flag
f=rnd*32.0f+32.0f; if (tnpc->wait_disable<f) tnpc->wait_disable=f;
stealing(tplayer,tplayer->mobj); tplayer->mobj=NULL;
}
goto skip_pickup;
}
}
x2=0;
x3=tplayer->mobj->type;
x5=0;
if (x3==95) x2=6; //95 grapes 3 B *6
if (x3==96) x2=1; //96 butter 1 C *1
if (x3==115) {x2=5; x5=1;} //115 wine 6 6 5 5 4 6 6 4 4 =5 C *5
if (x3==116) {x2=4; x5=1;} //116 mead 4 5 3 2 5 4 4 4 3 =4 C *4
if (x3==117) {x2=4; x5=1;} //117 ale 3 7 2 5 3 3 3 4 2 =4 C *4
if (x3==128) x2=12; //128 bread 3 3 (2 loaves) c A *12
if (x3==129) x2=16; //129 meat (legs) c 4 3 3 4 4 4 4 4 4 A *16
if (x3==130) x2=8; //130 rolls 1 2 2 A *m
if (x3==131) x2=12; //131 cake 8 5 B *12
if (x3==132) x2=10; //132 cheese 6 5 B *10
if (x3==133) x2=16; //133 ham (looks like steak) 3 5 A *16
if (x3==135) x2=28; //135 horse chops (gargoyle food) A *28
if (x3==179) {x2=2; x5=1;} //179 bucket of water *this item needs modifying after use (1) B *2
if (x3==180) {x2=8; x5=1;} //180 bucket of milk *this item needs modifying after use 3 5 =4 B *8
if (x3==184) x2=10; //184 jar of honey *this item needs modifying after use 10 C *10
if (x3==209) x2=12; //209 small hanging meat 6 B *12
if (x3==210) x2=28; //210 big hanging meat 9 6 A =7 *28
if (x3==265) x2=6; //265 fish 3 B *6
if (x2){
x2*=4;
if (myobj->info&2){ //<-NPC
tnpc=(npc*)myobj->more;
if (tnpc->player==tplayer){
x4=tnpc->food;
if ((x4+x2)>255){
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," full!"); NET_send(NETplayer,tplayer->net,t); goto skip_pickup;
}
x4+=x2;
tnpc->food=x4;
txtset(t,"?"); t->d2[0]=8; txtaddchar(t,255); txtadd(t,tnpc->name);
if (x5) txtadd(t," drinks the "); else txtadd(t," eats the ");
y2=objname[(tplayer->mobj->type&1023)*2];
y3=objname[(tplayer->mobj->type&1023)*2+1];
txtNEWLEN(t2,y3);
memcpy(&t2->d2[0],&objname2[y2],y3);
txtadd(t,t2); txtadd(t,".");
NET_send(NETplayer,tplayer->net,t);
stealing(tplayer,tplayer->mobj);
//change or destroy item?
if (obji[sprlnk[tplayer->mobj->type&1023]+(tplayer->mobj->type>>10)].flags&4096){
if (tplayer->mobj->more2!=1){ //more than 1!
tplayer->mobj->more2--; goto skip_pickup;
}
}
if ((x3==179)||(x3==180)) {tplayer->mobj->type=178; tplayer->mobj_last=NULL; goto skip_pickup;}
if (x3==184) {tplayer->mobj->type=183; tplayer->mobj_last=NULL; goto skip_pickup;}
OBJremove(tplayer->mobj); OBJrelease(tplayer->mobj);
tplayer->mobj=NULL; //?
//stupid comment like in ultima7??
}
goto skip_pickup;
}
}
if ((tplayer->mobj->type>=242)&&(tplayer->mobj->type<=249)){ //rune
if (myobj2=(object*)myobj->prev){ if ((myobj2->type&1023)==73){ //moonstone
if ((myobj2->type>>10)==(tplayer->mobj->type-242)){ //same type
tplayer->GNPCflags[3]|=(1<<(myobj2->type>>10));
goto skip_pickup;
}//same type
}}//moonstone
}//rune
if (tplayer->mobj->type==63){ //lockpick
if (myobj->type==(98+2048)){ //locked chest
myobj3=(object*)tplayer->party[0]; tnpc=(npc*)myobj3->more;
stealing(tplayer,tplayer->mobj);
if (((rnd*64)+(rnd*tnpc->i))>=56){ //success
OBJsave(myobj->x,myobj->y);
myobj->type=OBJ_CHEST+1024;
}else{
x2=rnd*2; if (x2){ //break pick!
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Key broke!"); NET_send(NETplayer,tplayer->net,t);
if (tplayer->mobj->more2==1) tplayer->mobj=NULL; else tplayer->mobj->more2--;
}//x2
}
goto skip_pickup;
}
}
//lock pick on chest??
//WOW is that a door at all???
x2=myobj->type&1023;
if ((x2>=297)&&(x2<=300)){ //door
if ((myobj->type>>10)>=4){ //closed
if (tplayer->mobj->type==63) goto lockpick; //lockpick
if (tplayer->mobj->type==64){ //key
lockpick:
myobj2=OBJfindlastall(x,y);
if (myobj2->info&8) myobj2=(object*)myobj2->more; //<-redirect
myobj2=OBJfindlastall(myobj2->x,myobj2->y); //2004
//GPF!
//txtnumint(t5,myobj2->more2);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
//txtnumint(t5,tplayer->mobj->more2);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
if ((myobj2->more2==0)&&(tplayer->mobj->type==63)){
if ((myobj->type>>12)!=2) goto skip_pickup;
myobj3=(object*)tplayer->party[0];
tnpc=(npc*)myobj3->more;
stealing(tplayer,tplayer->mobj);
if (((rnd*64)+(rnd*tnpc->i))>=56) goto lockpick2; //success
x2=rnd*2; if (x2){ //break pick!
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Key broke!"); NET_send(NETplayer,tplayer->net,t);
if (tplayer->mobj->more2==1) tplayer->mobj=NULL; else tplayer->mobj->more2--;
goto skip_pickup;
}
}
if ((myobj2->more2)&&(tplayer->mobj->type==63)) goto skip_pickup;
if (myobj2->more2==tplayer->mobj->more2){
stealing(tplayer,tplayer->mobj);
lockpick2:
//unlock/relock door!
//myobj->more2=
if (myobj->info&8) myobj=(object*)myobj->more; //<-redirect
x2=myobj->type>>12;
if ((x2!=2)&&(tplayer->mobj->type==63)) goto skip_pickup;
if (x2==1){ //unlocked->lock
myobj->type=(myobj->type&4095)+(2<<12);
myobj3=(object*)myobj->more;
myobj3->type=(myobj3->type&4095)+(2<<12);
}
if (x2==2){
myobj->type=(myobj->type&4095)+(1<<12);
myobj3=(object*)myobj->more;
myobj3->type=(myobj3->type&4095)+(1<<12);
}
goto skip_pickup;
}
}
}//closed
}//door
goto skip_pickup;
}//use item on item
//}else{
if (myobj->info&2){
tnpc2=(npc*)myobj->more;
if (tnpc2->player==tplayer){
tnpc=tnpc2;
i=-1;
if (tnpc->player){ if (tnpc->player->party[0]){ if ((npc*)tnpc->player->party[0]->more==tnpc){
i=0;
}}}
goto sprite_drop;
}
}
if (i==394){
if ((x==921)&&(y==851)){
if (tplayer->mobj->type==394){
goto dropallow;
}}}
if (i==396){
if ((x==925)&&(y==851)){
if (tplayer->mobj->type==396){
goto dropallow;
}}}
if (i==62){
if ((x==923)&&(y==850)){
if (tplayer->mobj->type==62){
goto dropallow;
}}}
if (obji[i2].flags&512){
dropallow:
z2=9; myobj2=NULL;
for (z=0;z<=7;z++){
if (myobj3=tplayer->party[z]){
if (OBJcheckbolt(myobj3->x,myobj3->y,x,y)==FALSE){
z3=abs(myobj3->x-x); z4=abs(myobj3->y-y); if (z4>z3) z3=z4;
if (z3<z2){
myobj2=myobj3;
z2=z3;
}
}
}
}
if (myobj2){
if ((tplayer->mobj->type&1023)==420){ //skiff drop
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a balloon here!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
if (tplayer->mobj->info&256){ //drop quest item
//brit lens
if (tplayer->mobj->type==394){
if ((x==921)&&(y==851)){
tplayer->GNPCflags[18]|=2;
tplayer->mobj=NULL; //clear selected mouse object
goto itemdropped2;
}
}
//garg lens
if (tplayer->mobj->type==396){
if ((x==925)&&(y==851)){
tplayer->GNPCflags[18]|=4;
tplayer->mobj=NULL; //clear selected mouse object
goto itemdropped2;
}
}
//vortex cube
if (tplayer->mobj->type==62){
if ((x==923)&&(y==850)){
//check internal contents of vortex cube!
x2=0;
myobj2=(object*)tplayer->mobj->more;
checkvortexcube:
if (myobj2){
x2|=(1<<(myobj2->type>>10));
if (myobj2=(object*)myobj2->next) goto checkvortexcube;
}
if (x2!=255){
txtset(t,"?Place the eight moonstones within the Vortex Cube.");
t->d2[0]=8;
NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
tplayer->GNPCflags[18]|=1;
tplayer->mobj=NULL; //clear selected mouse object
goto itemdropped2;
}
}
txtset(t,"?");
t->d2[0]=8;
txtadd(t,"You cannot put a quest item here!");
NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
if ((tplayer->mobj->type&1023)==414){ //skiff drop
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a skiff here!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
if (tplayer->mobj->type==149){ //deed drop
//in current boat?
if ((object*)tplayer->mobj->more==tplayer->party[0]){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot drop this deed now!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
//currently holding the boat this deed points to?
myobj3=(object*)tplayer->mobj->more;
//txtnumint(t5,myobj->more2);
if ((myobj3->x==0)&&(myobj3->y==0)){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You must drop the skiff first!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
}
if (tplayer->mobj->type==448){//horse papers
if (((object*)tplayer->mobj->more)->x==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot drop these horse papers now!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
crt2=(creature*)((object*)tplayer->mobj->more)->more;
crt2->respawn_y=0xFFFF;
}//448
x5=OBJlist(tplayer->mobj); //x5=last object number
OBJlist_last=NULL;
//check if drop location is a house storage shelf
for (i3=1;i3<=255;i3++){
for (i4=0;i4<housestoragenext[i3];i4++){
if (x==housestoragex[i3][i4]){ if (y==housestoragey[i3][i4]){
//stolen items check
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->info&128){ //stolen item!
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put stolen things here!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}//stolen item!
}//y6
//8 stack limit check
myobj=od[housestoragey[i3][i4]][housestoragex[i3][i4]];
x2=0;
countstacklimit: if (myobj->next){x2++; myobj=(object*)myobj->next; goto countstacklimit;}
if (x2>=8){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot stack more than 8 items here! Put items in containers to store more here."); NET_send(NETplayer,tplayer->net,t);
goto itemdropped2;
}
}}//x,y
}//i4
}//i3
//clear notforsale marks
for(y6=0;y6<x5;y6++){
OBJlist_list[y6]->info|=32768; OBJlist_list[y6]->info^=32768;
}//y6
/*
if (tplayer->mobj->info&128){//stolen item
for (i3=0;i3<=15;i3++) if (stolenitemwarning[i3]==tplayer->mobj) goto stolenitem_alreadyadded;
for (i3=0;i3<=15;i3++){
if (stolenitemwarning[i3]==NULL){
stolenitemwarning[i3]=tplayer->mobj;
stolenitemwarning_wait[i3]=2.0f;
stolenitemwarning_player[i3]=tplayer;
goto stolenitem_alreadyadded;
}//==NULL
}//i3
}//stolen item
stolenitem_alreadyadded:
*/
if (tplayer->mobj->info&128){//stolen item
i3=SFnew(x,y); //destination is more important than the source
sf[i3].type=21;//stolen item warning
sf[i3].x=x;
sf[i3].y=y;
sf[i3].more=tplayer->mobj->type;
sf[i3].wait=2.0f;
}
//drop sfx!
i3=SFnew(x,y); //destination is more important than the source
sf[i3].type=9; //GENERIC throw object
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].x2=x;
sf[i3].y2=y;
sf[i3].more=0xFFFF;
sf[i3].wait=tplayer->mobj->type;
//drop sound effect
if ((tplayer->mobj->type&1023)==88){//gold
if (tplayer->mobj->more2>=5){
i3=SFnew(x,y);
sf[i3].type=4; //sound
sf[i3].x=x;
sf[i3].y=y;
sf[i3].wait=1.0f; //NULL
sf[i3].more=6; //coinmany
}else{
i3=SFnew(x,y);
sf[i3].type=4; //sound
sf[i3].x=x;
sf[i3].y=y;
sf[i3].wait=1.0f; //NULL
sf[i3].more=7; //coinfew
}
}
//smash it?
i4=0;
if ((tplayer->mobj->type&1023)==275) i4=1; //potions
if (tplayer->mobj->type==115) i4=1; //
if (tplayer->mobj->type==116) i4=1; //
if (tplayer->mobj->type==117) i4=1; //
if (tplayer->mobj->type==118) i4=1; //
if (tplayer->mobj->type==119) i4=1; //
if (tplayer->mobj->type==120) i4=1; //mug
if (tplayer->mobj->type==123){ //mirror
if ((abs(myobj2->x-x)>1)||(abs(myobj2->y-y)>1)){
sf[i3].wait+=32768; tplayer->mobj->type=123+1024*2;
stealing(tplayer,tplayer->mobj);
}
}
if ((tplayer->mobj->type==179)||(tplayer->mobj->type==180)){ //bucket of milk/water
if ((abs(myobj2->x-x)>1)||(abs(myobj2->y-y)>1)){
tplayer->mobj->type=178;
sf[i3].wait=tplayer->mobj->type;
stealing(tplayer,tplayer->mobj);
}
}
if (tplayer->mobj->type==92) i4=1; //silver snake venom
if (tplayer->mobj->type==161) i4=1; //jug
if (tplayer->mobj->type==83) i4=1; //oil flask
if (tplayer->mobj->type==48) i4=1; //glass sword
if (tplayer->mobj->type==183) i4=1; //jar
if (tplayer->mobj->type==184) i4=1; //jar with honey
if ((abs(myobj2->x-x)<=1)&&(abs(myobj2->y-y)<=1)) i4=0;
if (i4){
sf[i3].wait+=32768; OBJrelease(tplayer->mobj);
stealing(tplayer,tplayer->mobj);
}else{
OBJadd(x,y,tplayer->mobj);
}
tplayer->mobj=NULL; //clear selected mouse object
goto itemdropped2;
//}//<=8
//}
//}}
}//myobj2
itemdropped2:;
} //bt flag
}//myobj!=NULL
else
{
//myobj==NULL hence no item underneath!
if (tplayer->action==1){ //use item on basetile
if (tplayer->mobj->type==87){ //orb of the moons
if (tplayer->GNPCflags[23]==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You can't figure out how to use it!"); NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}
if (bt[y][x]&1024){ //walkable location
if (myobj2=tplayer->party[tplayer->selected_partymember]){
if (abs(myobj2->x-x)<=2){ if (abs(myobj2->y-y)<=2){
tnpc=(npc*)myobj2->more;
if (tnpc->wait_disable<=0){
myobj3=OBJnew();
myobj3->type=84+1024;
myobj3->info=3<<4; //set flags as temp OBJ
myobj3->more2=(x-myobj2->x+2)+(y-myobj2->y+2)*5+1;
OBJadd(x,y,myobj3);
myobj3=OBJnew();
myobj3->type=84;
myobj3->info=3<<4; //set flags as temp OBJ
myobj3->more2=(x-myobj2->x+2)+(y-myobj2->y+2)*5+1;
OBJadd(x-1,y,myobj3);
tnpc->wait_disable+=8.0f;
}else{
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," busy!"); NET_send(NETplayer,tplayer->net,t);
}
}}//x,y
}//myobj2
}//&1024
goto skip_pickup;
}//orb
//myobj3=OBJnew(); myobj3->type=87; myobj3->more2=0; myobj3->info=256; //orb of moons
/*
myobj2=OBJnew();
myobj2->type=84+1024;
myobj2->info=3<<4; //set flags as temp OBJ
OBJadd(tpx+x,tpy+y,myobj2);
myobj2=OBJnew();
myobj2->type=84;
myobj2->info=3<<4; //set flags as temp OBJ
OBJadd(tpx+x-1,tpy+y,myobj2);
*/
z2=1;
for (z=0;z<=7;z++){
if (myobj2=tplayer->party[z]){
if (abs(myobj2->x-x)<=1){
if (abs(myobj2->y-y)<=1){
z2=0;
}} }}
if (z2) goto skip_pickup;
if ((tplayer->mobj->type&1023)==264){ //fishing line
if (((bt[y][x]&1023)>=8)&&((bt[y][x]&1023)<16)){ //in water
tnpc=(npc*)tplayer->party[0]->more;
if (tnpc->wait_disable<=0){
if ((rnd*8.0f)<1.0f){
//add fish!
myobj3=OBJnew(); myobj3->type=265; //<-fish
f=WTfind(myobj3);
if ((tnpc->wt+f)<=tnpc->wt_max){
additemroot(tnpc,myobj3);
tnpc->upflags|=32;
}//weight check
}else{
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Didn't get a fish."); NET_send(NETplayer,tplayer->net,t);
}
tnpc->wait_disable+=8.0f;
}else{//wait
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," busy!"); NET_send(NETplayer,tplayer->net,t);
}
}
goto skip_pickup;
}
if ((tplayer->mobj->type&1023)==104){ //shovel
if (od[y][x]==NULL){
if (((bt[y][x]&1023)>=108)&&((bt[y][x]&1023)<112)){ //on soil
if ((x==707)&&(y==835)){ //hole location 707 835
if (tplayer->craft==NULL){
if (usinghorse(tplayer)==NULL){
if (tplayer->GNPCflags[8]==1){//know location
//if another resurrectable body is being carried drop it near entrance
x5=0;
for (x6=0;x6<=7;x6++){
if (myobj3=getpartymemberobj(tplayer,x6)){
tnpc3=(npc*)myobj3->more;
tnpc3->upflags|=32;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if ((OBJlist_list[y6]->type&1023)==339){ //dead body
//scan resurrect list
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_body[i3]==OBJlist_list[y6]){
OBJremove(OBJlist_list[y6]);
OBJadd(704,832,OBJlist_list[y6]);
goto pirateholefix_bodyremoved;
}}}
pirateholefix_bodyremoved:;
}}
//transport party to underground
for (i4=7;i4>=0;i4--){
if (tplayer->party[i4]!=NULL){
OBJremove(tplayer->party[i4]);
OBJadd(179+1024,211,tplayer->party[i4]);
}//->party
}//i4
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You dig a hole."); NET_send(NETplayer,tplayer->net,t);
}else{//dont know location
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Why dig here?"); NET_send(NETplayer,tplayer->net,t);
}
goto skip_pickup;
}//horse
}//craft
}//hole x,y
if ((tplayer->party[0]->x>=1024)&&(tplayer->party[0]->y<256)){ //underground //TODO do real underground check
tnpc=(npc*)tplayer->party[0]->more;
if (tnpc->wait_disable<=0){
if ((rnd*12.0f)<1.0f){
myobj3=OBJnew(); myobj3->type=89; myobj3->more2=1;
//fountain?
myobj3->info|=112; OBJadd(x,y,myobj3);
}else{
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Nothing!"); NET_send(NETplayer,tplayer->net,t);
}
tnpc->wait_disable+=8.0f-((tplayer->mobj->more2)&15)*0.5f;
}else{//wait
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," busy!"); NET_send(NETplayer,tplayer->net,t);
}
}//underground
}//soil
}//no objects
goto skip_pickup;
}//shovel
if ((tplayer->mobj->type&1023)==OBJ_TMAP){ //treasure map
if (od[y][x]==NULL){
if (((bt[y][x]&1023)==1)||(((bt[y][x]&1023)>=52)&&((bt[y][x]&1023)<64))||(((bt[y][x]&1023)>=73)&&((bt[y][x]&1023)<96))||(((bt[y][x]&1023)>=108)&&((bt[y][x]&1023)<112))){
tnpc=(npc*)tplayer->party[0]->more;
x2=0;
if ((tnpc->wep_right)&&(tnpc->wep_right->type&1023)==OBJ_SHOVEL) {x2=1;}
if ((tnpc->wep_left)&&(tnpc->wep_left->type&1023)==OBJ_SHOVEL) {x2=2;}
if (x2){
if (tnpc->wait_disable<=0){
x3=1;
if (abs((int)(((tplayer->mobj->more2&1023)-x)<=2)) && (abs(((int)((tplayer->mobj->more2>>10)&1023)-y)<=2))){
x3=2+rnd*2;
object* item000001=OBJaddnew(x,y,OBJ_CHEST+1024*x3,112,0);//chest
for (x3=0;x3<24;x3++) {
x4=randchestitem();
x5=x4>>10;
x4=x4&1023;
object* item000002=OBJaddnew(x,y,x4+1024*0,112,x5);
/*for (y7=0;y7<1000000000;y7++) { //for testing the new enhance system
ENHANCEnewn(item000002,4,4);
}*/
ENHANCEnewn(item000002,2,4);
OBJremove(item000002);//remove from the map (so it can go in a container)
OBJaddtocontainer(item000001, item000002); //put this item inside its parent
}
tplayer->mobj=NULL;
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You dig up a chest."); NET_send(NETplayer,tplayer->net,t);
x3=2; //double wait time for digging up the treasure.
}else{
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Nothing!"); NET_send(NETplayer,tplayer->net,t);
}
if(x2==1){
tnpc->wait_disable+=(8.0f-((tnpc->wep_right->more2)&15)*0.5f)*x3;
}else{
tnpc->wait_disable+=(8.0f-((tnpc->wep_left->more2)&15)*0.5f)*x3;
}
}else{//wait
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," busy!"); NET_send(NETplayer,tplayer->net,t);
}
}else{
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You need to equip a shovel to dig."); NET_send(NETplayer,tplayer->net,t);
}
}
}//no objects
goto skip_pickup;
}//treasure map
//other items?
goto skip_pickup;
}//end use item on basetile
if ((tplayer->mobj->type&1023)==414){ //skiff drop
z2=0;
if (od[y][x]) z2=1;
z=bt[y][x]&1023;
if ((z<8)||(z>=48)){//not water
if ((bt[y][x]&1024)==0){//not walkable
z2=1;
}
}
if (z2){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot put a skiff here!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped;
}
goto skiffdrop;
}
if (bt[y][x]&1024){
skiffdrop:
//can it be dropped from any party member in the location?
//for (z=0;z<=7;z++){
//myobj2=tplayer->party[z];
//if (myobj2!=NULL){
//if (OBJcheckbolt(myobj2->x,myobj2->y,x,y)==FALSE){
//if ((abs(myobj2->x-x)<=8)&&(abs(myobj2->y-y)<=8)){
z2=9; myobj2=NULL;
for (z=0;z<=7;z++){
if (myobj3=tplayer->party[z]){
if (OBJcheckbolt(myobj3->x,myobj3->y,x,y)==FALSE){
z3=abs(myobj3->x-x); z4=abs(myobj3->y-y); if (z4>z3) z3=z4;
if (z3<z2){
myobj2=myobj3;
z2=z3;
}
}
}
}
if (myobj2){
if ((tplayer->mobj->type&1023)==420){ //balloon drop
if ((abs(myobj2->x-x)>1)||(abs(myobj2->y-y)>1)){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot throw a balloon!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped;
}
if (tplayer->craft==NULL){
if (usinghorse(tplayer)==NULL){
if ((tplayer->party[tplayer->selected_partymember]->x<1024)||(tplayer->party[tplayer->selected_partymember]->y>=256)){
//use balloon
myobj=tplayer->mobj; itemused=2; i=myobj->type&1023; i2=myobj->type>>10; tplayer->mobj=NULL; goto useinventoryitem;
}
}
}
goto itemdropped;
}
if (tplayer->mobj->info&256){ //drop quest item
txtset(t,"?");
t->d2[0]=8;
txtadd(t,"You cannot put a quest item here!");
NET_send(NETplayer,tplayer->net,t);
goto itemdropped;
}
if ((tplayer->mobj->type&1023)==414){//skiff drop
z2=0;
if (abs(myobj2->x-x)==1){
z=bt[myobj2->y][x]&1023;
if ((z<8)||(z>=48)){//not water
if ((bt[myobj2->y][x]&1024)==0){//not walkable
z2=1;
}
}
}
if (abs(myobj2->y-y)==1){
z=bt[y][myobj2->x]&1023;
if ((z<8)||(z>=48)){//not water
if ((bt[y][myobj2->x]&1024)==0){//not walkable
z2=1;
}
}
}
if ((abs(myobj2->x-x)>1)||(abs(myobj2->y-y)>1)) z2=1;
if (z2){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot throw a skiff!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped;
}
}
if (tplayer->mobj->type==149){ //deed drop
//in current boat?
if ((object*)tplayer->mobj->more==tplayer->party[0]){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot drop this deed now!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped;
}
//currently holding the boat this deed points to?
myobj3=(object*)tplayer->mobj->more;
if ((myobj3->x==0)&&(myobj3->y==0)){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You must drop the skiff first!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped;
}
}
if (tplayer->mobj->type==448){//horse papers
if (((object*)tplayer->mobj->more)->x==0){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot drop these horse papers now!"); NET_send(NETplayer,tplayer->net,t);
goto itemdropped;
}
crt2=(creature*)((object*)tplayer->mobj->more)->more;
crt2->respawn_y=0xFFFF;
}//448
x5=OBJlist(tplayer->mobj); //x5=last object number
OBJlist_last=NULL;
//clear notforsale marks
for(y6=0;y6<x5;y6++){
OBJlist_list[y6]->info|=32768; OBJlist_list[y6]->info^=32768;
}//y6
/*
if (tplayer->mobj->info&128){//stolen item
for (i3=0;i3<=15;i3++) if (stolenitemwarning[i3]==tplayer->mobj) goto stolenitem_alreadyadded2;
for (i3=0;i3<=15;i3++){
if (stolenitemwarning[i3]==NULL){
stolenitemwarning[i3]=tplayer->mobj;
stolenitemwarning_wait[i3]=2.0f;
stolenitemwarning_player[i3]=tplayer;
goto stolenitem_alreadyadded2;
}//==NULL
}//i3
}//stolen item
stolenitem_alreadyadded2:
*/
if (tplayer->mobj->info&128){//stolen item
i3=SFnew(x,y); //destination is more important than the source
sf[i3].type=21;//stolen item warning
sf[i3].x=x;
sf[i3].y=y;
sf[i3].more=tplayer->mobj->type;
sf[i3].wait=2.0f;
}
//OBJadd(x,y,tplayer->mobj);
//drop sfx!
i3=SFnew(x,y); //destination is more important than the source
sf[i3].type=9; //GENERIC throw object
sf[i3].x=myobj2->x;
sf[i3].y=myobj2->y;
sf[i3].x2=x;
sf[i3].y2=y;
sf[i3].more=0xFFFF;
sf[i3].wait=tplayer->mobj->type;
//drop sound effect
if ((tplayer->mobj->type&1023)==88){//gold
if (tplayer->mobj->more2>=5){
i3=SFnew(x,y);
sf[i3].type=4; //sound
sf[i3].x=x;
sf[i3].y=y;
sf[i3].wait=1.0f; //NULL
sf[i3].more=6; //coinmany
}else{
i3=SFnew(x,y);
sf[i3].type=4; //sound
sf[i3].x=x;
sf[i3].y=y;
sf[i3].wait=1.0f; //NULL
sf[i3].more=7; //coinfew
}
}
//smash it?
i4=0;
if ((tplayer->mobj->type&1023)==275) i4=1; //potions
if (tplayer->mobj->type==115) i4=1; //
if (tplayer->mobj->type==116) i4=1; //
if (tplayer->mobj->type==117) i4=1; //
if (tplayer->mobj->type==118) i4=1; //
if (tplayer->mobj->type==119) i4=1; //
if (tplayer->mobj->type==120) i4=1; //mug
if (tplayer->mobj->type==123){ //mirror
if ((abs(myobj2->x-x)>1)||(abs(myobj2->y-y)>1)){
sf[i3].wait+=32768; tplayer->mobj->type=123+1024*2;
stealing(tplayer,tplayer->mobj);
}
}
if ((tplayer->mobj->type==179)||(tplayer->mobj->type==180)){ //bucket of milk/water
if ((abs(myobj2->x-x)>1)||(abs(myobj2->y-y)>1)){
tplayer->mobj->type=178;
sf[i3].wait=tplayer->mobj->type;
stealing(tplayer,tplayer->mobj);
}
}
if (tplayer->mobj->type==92) i4=1; //silver snake venom
if (tplayer->mobj->type==161) i4=1; //jug
if (tplayer->mobj->type==83) i4=1; //oil flask
if (tplayer->mobj->type==48) i4=1; //glass sword
if (tplayer->mobj->type==183) i4=1; //jar
if (tplayer->mobj->type==184) i4=1; //jar with honey
if ((abs(myobj2->x-x)<=1)&&(abs(myobj2->y-y)<=1)) i4=0;
if (i4){
sf[i3].wait+=32768; OBJrelease(tplayer->mobj);
stealing(tplayer,tplayer->mobj);
}else{
OBJadd(x,y,tplayer->mobj);
}
tplayer->mobj=NULL; //clear selected mouse object
goto itemdropped;
//}//<=8
//}
//}}
}//myobj2
itemdropped:;
} //bt flag
} //myobj==NULL
} //clicked in vf
goto skip_pickup;
} //mobj!=NULL
//mobj==NULL
//pickup:
if ((tplayer->mf==255)&&(tplayer->key&KEYmbclick)){
if (tplayer->action==0){
x=tpx+tplayer->mx/32;
y=tpy+tplayer->my/32;
myobj=OBJfindlast(x,y);
if (myobj!=NULL){
if (myobj->type==51){ //force field
myobj2=(object*)myobj->prev;
if (playerlist[tpl]->GNPCflags[3]&(1<<(myobj2->type>>10))) myobj=(object*)myobj->prev;
}//force field
i=myobj->type;
//i2=i>>10; //26/11/2004 removed for Sherry compatibility
i2=sprlnk[i&1023];
if (((obji[i2].flags&128)!=0)||(keyon[VK_SPACE]&&U6O_DEBUG)){
//check if item is next to player
static unsigned char pickup_partymember;
z2=0;
for (z=7;z>=0;z--){
myobj2=tplayer->party[z];
if (myobj2!=NULL){
if (abs(myobj2->x-myobj->x)<=1){
if (abs(myobj2->y-myobj->y)<=1){
z2=1; pickup_partymember=z;
}} }}
if (z2==1){
if ((myobj->info&112)==0){ //this is a fixed map object
//void OBJsave(unsigned short x,unsigned short y){
OBJsave(myobj->x,myobj->y);
//MessageBox(NULL,"OBJsave() called","Ultima 6 Online",MB_OK);
//copy everythng! yes everything!
//*note no temp flash is needed as a warning
//scan through the next list, if we find a container, add it to the list
//if there were any container items copy them, then try again
//idea! set temp flag while scanning!! (if possible)
//set temp flag of any object that can be picked up/used
}
if ((myobj->type&1023)==73){ //moonstone
if ((tplayer->GNPCflags[4]&(1<<(myobj->type>>10)))==0){
tplayer->GNPCflags[4]|=(1<<(myobj->type>>10));
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
if ((myobj->type>=242)&&(myobj->type<=249)){ //rune
if (myobj->info&256){ //must be a quest item
if ((tplayer->GNPCflags[5]&(1<<(myobj->type-242)))==0){
tplayer->GNPCflags[5]|=(1<<(myobj->type-242));
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
}
if (myobj->type==(275+2*1024)){ //potions
if (myobj->info&256){
if ((tplayer->GNPCflags[32]&myobj->more2)==0){
tplayer->GNPCflags[32]|=myobj->more2;
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
}
if ((myobj->type>=400)&&(myobj->type<=407)){ //map(0-7)
if (myobj->info&256){ //must be a quest item
if ((tplayer->GNPCflags[7]&(1<<(myobj->type-400)))==0){
tplayer->GNPCflags[7]|=(1<<(myobj->type-400));
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
}
if (myobj->type==62){ //vortex cube
if ((myobj->x==1939)&&(myobj->y==57)){
if ((tplayer->GNPCflags[6]&(1<<1))==0){
tplayer->GNPCflags[6]|=(1<<1);
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
if ((myobj->x==923)&&(myobj->y==850)){
goto nopickup;
}
}
if (myobj->type==389){ //silver tablet
if ((tplayer->GNPCflags[6]&(1<<2))==0){
tplayer->GNPCflags[6]|=(1<<2);
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
if (myobj->type==390){ //silver tabletII
if ((tplayer->GNPCflags[6]&(1<<3))==0){
tplayer->GNPCflags[6]|=(1<<3);
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
if (myobj->type==270){ //balloon plans
if ((tplayer->GNPCflags[6]&(1<<4))==0){
tplayer->GNPCflags[6]|=(1<<4);
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
if (myobj->type==395){ //broken gargoyle lens
if ((tplayer->GNPCflags[6]&(1<<5))==0){
tplayer->GNPCflags[6]|=(1<<5);
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info;
tplayer->mobj=myobj2;
}
goto nopickup;
}
if (myobj==nuggetsfix){ //nuggets
if (tplayer->online>=1536){
if ((tplayer->GNPCflags[6]&(1<<6))==0){
tplayer->GNPCflags[6]|=(1<<6);
//duplicate it
myobj2=OBJnew(); myobj2->type=myobj->type; myobj2->info=myobj->info; myobj2->more2=myobj->more2;
tplayer->mobj=myobj2;
}
}
goto nopickup;
}
if (myobj->type==394){ //brit lens
goto nopickup;
}
if (myobj->type==396){ //garg lens
goto nopickup;
}
if (myobj->type==173){ //trap
if ((myobj->info&(1<<9))==0) goto nopickup;
OBJsave(myobj->x,myobj->y);
myobj->more2=tplayer->id; //id
myobj->info|=(1<<9);
if (tnpc->protection==0){
tnpc=(npc*)tplayer->party[pickup_partymember]->more;
x6=tnpc->hp>>3; if (!x6) x6=1; //-1/8th health
tnpc->hp-=x6;
i3=SFnew(tplayer->party[pickup_partymember]->x,tplayer->party[pickup_partymember]->y);
sf[i3].type=1; //attack
sf[i3].x2=x6;
sf[i3].x=tplayer->party[pickup_partymember]->x;
sf[i3].y=tplayer->party[pickup_partymember]->y;
sf[i3].wait=0.125f; //NULL
sf[i3].more=1;
tnpc->upflags|=2; //hp
txtset(t,"?"); t->d2[0]=8; txtadd(t,tnpc->name); txtadd(t," wounded!"); NET_send(NETplayer,tplayer->net,t);
}//protection
}//173
if ((myobj->type&1023)==414){ //skiff pickup
if (myobj->info&2) goto nopickup; //in use!
if ((myobj->info&(1<<9))==0){ //NOT free skiff
//deed check
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==149){ //deed
if (OBJlist_list[y6]->more==myobj) goto skiffpickup;
}
}
}//NOT free skiff
txtset(t,"?"); t->d2[0]=8; txtadd(t,"A deed is required!"); NET_send(NETplayer,tplayer->net,t);
goto nopickup;
}
skiffpickup:
//if (keyon[VK_SHIFT]) CLIENTplayer->key|=KEYquan;
if (tplayer->key&KEYquan){
if (tplayer->quan){
if (obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].flags&4096){
if (tplayer->quan<myobj->more2){
myobj2=OBJnew();
myobj2->type=myobj->type;
myobj2->info=myobj->info;
myobj2->more2=tplayer->quan;
myobj->more2-=tplayer->quan;
tplayer->mobj=myobj2;
goto nopickup;
}//<
}//multiple
}//->quan
}//KEYquan
tplayer->mobj=myobj;
OBJremove(tplayer->mobj);
//if (objb_last>28039) MessageBox(NULL,"OBJnew: prep1","Ultima 6 Online",MB_OK);
nopickup:;
}
} //flag check
} //mobj!=NULL
} //action0
if (tplayer->action==1){ //use!
x=tpx+tplayer->mx/32;
y=tpy+tplayer->my/32;
z2=0;
for (z=0;z<=7;z++){
myobj2=tplayer->party[z];
if (myobj2!=NULL){
if (abs(myobj2->x-x)<=1){
if (abs(myobj2->y-y)<=1){
z2=1;
}} }}
if (z2==0) goto finishuse;
myobj=tplayer->party[tplayer->selected_partymember];
//tnpc=(npc*)myobj->more;
/*
x2=myobj->x;
y2=myobj->y;
if (OBJcheckbolt(x2,y2,x,y)){
myobj=OBJnew();
myobj->type=338+2048;
OBJadd(OBJcheckbolt_x,OBJcheckbolt_y,myobj);
}else{
//u6ob
i3=SFnew(x,y); //destination is more important than the source
sf[i3].type=2; //arrow
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].x2=x;
sf[i3].y2=y;
sf[i3].more=0xFFFF;
sf[i3].wait=1;
}
*/
itemused=0;
myobj=OBJfindlast(x,y);
retryuse:
if (myobj==NULL) {myobj=OBJfindlastall(x,y); itemused=1;}//check floating objects
if (myobj==NULL){
//basetile exceptions
/* disabled until katish's dungeon is implemented
//secret maze entry/exit
if ((x==193)&&(y==515)){
if (tplayer->craft==NULL){//not in a balloon (or a boat!)
if (usinghorse(tplayer)==NULL){//noone is riding a horse
partyadd(tplayer,1876,438);
}}}
if ((x==1876)&&(y==437)){
if (tplayer->craft==NULL){//not in a balloon (or a boat!)
if (usinghorse(tplayer)==NULL){//noone is riding a horse
partyadd(tplayer,192,514);
}}}*/
goto finishuse;
}
//next items are not people, scan backwards through living creatures to top item!
use_getprevitem:
if ((myobj->type&1023)!=430){//horses excepted(because you can use a horse)
if ((myobj->type&1023)!=431){//horses excepted(because you can use a horse)
if (obji[sprlnk[myobj->type&1023]].v4){
myobj=(object*)myobj->prev;
if (myobj) goto use_getprevitem;
goto finishuse;
}
}}
static object *use_beforeredirect;
i=myobj->type&1023;
i2=myobj->type>>10;
use_beforeredirect=myobj;
if ((myobj->info&8)==8) myobj=(object*)myobj->more; //redirector
//***primary player only objects
//crafts, ladders, etc
if (tplayer->craft){//if in a craft player can only exit that craft
if (myobj!=tplayer->party[0]) goto finishuse;
}
//horse exception: you cannot enter a craft if any partymember is on a horse
static unsigned char use_noladdercheck;
use_noladdercheck=0;
for (x3=0;x3<=7;x3++){
if (myobj3=tplayer->party[x3]){
tnpc3=(npc*)myobj3->more;
if (tnpc3->horse){use_noladdercheck=1; goto use_horseexceptionskip;}
}//myobj3
}//x3
myobj2=tplayer->party[0];
if (abs(myobj2->x-x)>1) goto playeronlyuse_skip;
if (abs(myobj2->y-y)>1) goto playeronlyuse_skip;
//skiff or raft
if (i==414 || i==415){
use_craft(tplayer,myobj); /* luteijn: replaces whole shebang */
goto finishuse;
}
//exit balloon
if (i==423){
//check if walking passable without balloon
i4=myobj->x; i5=myobj->y; OBJremove(myobj);
if (bt[i5][i4]&1024){
OBJadd(i4,i5,myobj);
use_craft(tplayer,myobj);
}else{
OBJadd(i4,i5,myobj);
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Not here!"); NET_send(NETplayer,tplayer->net,t);
}
goto finishuse;
}
if ((i==305)||(i==326)||(i==308)){ //ladder or dungeon or hole
lastchanceuse_ladder:
if (tplayer->craft==NULL){
//choose a point at the ladder and relocate the whole party to that square
x2=myobj->more2&0xFFFF;
y2=myobj->more2>>16;
//for (i4=7;i4>=0;i4--){
//if (tplayer->party[i4]!=NULL){
//OBJremove(tplayer->party[i4]);
//OBJadd(x2,y2,tplayer->party[i4]);
//}
//}
partyadd(tplayer,x2,y2);
}//->craft
goto finishuse;
}
use_horseexceptionskip:
if ((myobj->type&1023)==84){ //red gate, use gate, use moongate
if (myobj->more2==0xFFFFFFFF){//to toth's fantastic house ;)
x2=1342; y2=339; goto tothsgate;
}
if (myobj->more2==0xFFFFFFFE){//from toth's fantastic house ;)
x2=1362; y2=322; goto tothsgate;
}
i4=(myobj->info&112)>>4;
if (i4==1){
x3=1; y3=2;
if (myobj->more2){ //created by orb?
x3=myobj->more2-1; y3=x3/5; x3=x3-y3*5;
}
x2=orbx[x3][y3]; y2=orby[x3][y3];
//NEWCODE make one square left from avatar moongate go to player's house.
if (x3==1 && y3==2) {
if (i5=playerlist[tpl]->GNPCflags[28]){
x2=houseentrancex[i5];
y2=houseentrancey[i5];
}
}
if (U6O_DEBUG){
goto tothsgate; //for debugging
}
//NEWCODEEND
x3=1<<(x3+y3*5); if (tplayer->GNPCflags[22]&x3){ //been to dest?
tothsgate:
//for (i4=7;i4>=0;i4--){
//if (tplayer->party[i4]!=NULL){
//OBJremove(tplayer->party[i4]);
//OBJadd(x2,y2,tplayer->party[i4]);
//}//!=NULL
//}//i4
partyadd(tplayer,x2,y2);
}else{//&x3
txtset(t,"?"); t->d2[0]=8; txtadd(t,"You cannot enter a red moongate with a destination you have never visited!"); NET_send(NETplayer,tplayer->net,t);
}//&x3
}//i4
}//red gate
if ((myobj->type&1023)==85){ //moongate
if (moonphase!=255){
//for (i4=7;i4>=0;i4--){
//if (tplayer->party[i4]!=NULL){
//OBJremove(tplayer->party[i4]);
//OBJadd(moongatex[moonphase],moongatey[moonphase],tplayer->party[i4]);
//}
//}
partyadd(tplayer,moongatex[moonphase],moongatey[moonphase]);
}//moonphase
}//moongate
//boat
if (i==412){
use_craft(tplayer,myobj);
goto finishuse;
}
playeronlyuse_skip:
if (i==431){//horse(with rider)
tnpc2=(npc*)myobj->more;
if (tnpc2->player==tplayer){//so you can't dismount other players!
//find a walkable location to dismount
x3=myobj->x; y3=myobj->y;//set dismount location
//set as current location for ease of coding for now
//restore the horses head
myobj5=tnpc2->horse; tnpc2->horse=NULL;
crt2=(creature*)myobj5->more; crt2->wait+=8.0f;
OBJadd(myobj->x,myobj->y,myobj5);
myobj5->type=myobj->type-431+430;
//restore the horses tail
myobj6=(object*)tnpc2->more;
myobj6->more=myobj5;
myobj6->type=myobj6->type-431+430;
//restore the partymember
tnpc2->more=NULL;
myobj->type=tnpc2->originalobjtype; tnpc2->originalobjtype=NULL;
//move partymember to the side of the horse if possible
x4=0; y4=0;
//check adjacent squares of horse's head for walkability
if (bt[y3-1][x3]&1024){//walkable
x4=x3; y4=y3-1;
}
if (bt[y3][x3+1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3+1; y4=y3;}
x5=rnd*2; if (x5){x4=x3+1; y4=y3;}
}
if (bt[y3+1][x3]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3; y4=y3+1;}
x5=rnd*2; if (x5){x4=x3; y4=y3+1;}
}
if (bt[y3][x3-1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3-1; y4=y3;}
x5=rnd*2; if (x5){x4=x3-1; y4=y3;}
}
if ((x4==0)&&(y4==0)){//try from horse's tail
x3=myobj6->x; y3=myobj6->y;
if (bt[y3-1][x3]&1024){//walkable
x4=x3; y4=y3-1;
}
if (bt[y3][x3+1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3+1; y4=y3;}
x5=rnd*2; if (x5){x4=x3+1; y4=y3;}
}
if (bt[y3+1][x3]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3; y4=y3+1;}
x5=rnd*2; if (x5){x4=x3; y4=y3+1;}
}
if (bt[y3][x3-1]&1024){//walkable
if ((x4==0)&&(y4==0)){x4=x3-1; y4=y3;}
x5=rnd*2; if (x5){x4=x3-1; y4=y3;}
}
}//try from horse's tail
if (x4||y4){
OBJmove_allow=TRUE;
OBJmove2(myobj,x4,y4);
OBJmove_allow=FALSE;
}
}//so you can't dismount other players
goto finishuse;
}//horse(with rider)
if (i==430){//horse(unbridled)
for (x3=-1;x3<=7;x3++){
x4=x3; if (x3==-1) x4=tplayer->selected_partymember;
if (myobj2=tplayer->party[x4]){
if ( ((abs(myobj2->x-use_beforeredirect->x)<=1)&&(abs(myobj2->y-use_beforeredirect->y)<=1)) || ((abs(myobj2->x-myobj->x)<=1)&&(abs(myobj2->y-myobj->y)<=1)) ){
tnpc2=(npc*)myobj2->more;
if (tnpc2->horse==NULL){//check that npc is not currently on a horse
//lastly, check if we own the deed to that horse!
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}}//!=NULL,x6
OBJlist_last=NULL;
for(y6=0;y6<x5;y6++){
if (OBJlist_list[y6]->type==448){//horse papers
if ((object*)OBJlist_list[y6]->more==myobj) goto usehorse_gotpapers;
}
}
x5=0;
//is this a wild horse?
if ((abs(myobj->x-280)<=32)&&(abs(myobj->y-441)<=32)) x5=1;
if (myobj->info&4){crt2=(creature*)myobj->more; if (crt2->flags&128) x5=1;}
txtset(t,"?"); t->d2[0]=8;
if (x5) txtadd(t,"You don't own this horse!"); else txtadd(t,"You cannot ride a wild horse!");
NET_send(NETplayer,tplayer->net,t); goto finishuse;
usehorse_gotpapers:
tnpc2->originalobjtype=myobj2->type;
OBJremove(myobj2);
OBJadd(myobj->x,myobj->y,myobj2);
myobj2->type=myobj->type-430+431;
crt2=(creature*)myobj->more;
tnpc2->more=crt2->more; myobj3=(object*)crt2->more; myobj3->more=myobj2;//make rear end of horse point to partymember(myobj2)
myobj3->type=myobj3->type-430+431;
OBJremove(myobj);//remove front end of horse
tnpc2->horse=myobj;//backup pointer to front half of horse for later
goto finishuse;
}
}
}
}
goto finishuse;
}//horse(unbridled)
if (i==163) { //use bed in your own house to rest
if (i4=playerlist[tpl]->GNPCflags[28]){
//check if the bed is within boundaries
x7=myobj->x; y7=myobj->y;
if (x7>=housex1[i4]){ if (x7<=housex2[i4]){ if (y7>=housey1[i4]){ if (y7<=housey2[i4]){
for (y6=0;y6<housepnext[i4];y6++){
if (x7==housepx[i4][y6]){ if (y7==housepy[i4][y6]){
if (houseowner(playerlist[tpl],i4)) {tplayer->rest=17;}
goto finishuse;
}}//housepx,housepy
}//y
}}}}//boundries check
}
goto finishuse;
}
if (i==223){ //powder keg
OBJsave(myobj->x,myobj->y);
if (i2) {myobj->type=i; myobj->more2=tplayer->id; goto finishuse;}
myobj->type=i+1*1024;
myobj->info|=7680; //1111000000000 obj reserved timer
myobj->more2=tplayer->id;
stealing(tplayer,myobj);
goto finishuse;
}
if (i==334){ //secret door
use_basic_toggle(NULL,myobj);
OBJcheckflags(x,y);
goto finishuse;
}
if (i==164){ //fireplace
use_basic_toggle(NULL,myobj);
goto finishuse;
}
if (i==206){ //brazier
if (myobj->type>>10<2) {
use_basic_toggle(NULL,myobj);
} else {
/* purple/blue brazier can't be doused */
}
goto finishuse;
}
if (i==253){ //campfire
use_basic_toggle(NULL,myobj);
goto finishuse;
}
if (i==268){ //lever
use_toggle(NULL,myobj);
goto finishuse;
}
if (i==288){ //crank
use_toggle(NULL,myobj);
goto finishuse;
}
if (i==174){ //switch
use_toggle(NULL,myobj);
goto finishuse;
}
if (i==122){ //candle
OBJsave(myobj->x,myobj->y);
use_basic_toggle(NULL,myobj);
goto finishuse;
}
if (i==145){ //candelabra
OBJsave(myobj->x,myobj->y);
use_basic_toggle(NULL,myobj);
goto finishuse;
}
if (i==186){ //barrel
OBJsave(myobj->x,myobj->y);
use_basic_toggle(NULL,myobj);
goto finishuse;
}
if (i==192){ //crate
OBJsave(myobj->x,myobj->y);
use_basic_toggle(NULL,myobj);
goto finishuse;
}
if (i==98){ //chest
if (myobj->type>>10<2) { //can only use unlocked chests
OBJsave(myobj->x,myobj->y);
use_basic_toggle(NULL,myobj);
}
goto finishuse;
}
if (i==62){ //vortex cube use
if (tplayer->GNPCflags[19]){ //replay endgame sequence?
if ((myobj->x==923)&&(myobj->y==850)){
if ((tplayer->GNPCflags[18]&16)==0){
tplayer->GNPCflags[18]|=(2+4); //restore viewing of lenses
txtset(t,"?"); t->d2[0]=22; NET_send(NETplayer,tplayer->net,t); //play endgame sequence!
tplayer->GNPCflags[18]|=16; //endgame sequence played!
}
}
goto finishuse;
}
if ((tplayer->GNPCflags[18]&7)==7){
if ((myobj->x==923)&&(myobj->y==850)){
if (tplayer->party[0]){
tplayer->GNPCflags[18]|=8; //don't show codex!
tplayer->GNPCflags[19]=1; //sacred quest complete!!!
tplayer->karma+=20.0f;
tnpc3=(npc*)tplayer->party[0]->more;
tnpc3->s+=3; tnpc3->d+=3; tnpc3->i+=3;
tnpc3->mp_max=tnpc3->i*2; //primary party member INT*2
tnpc3->wt_max=tnpc3->s*4*100;
tnpc3->wt2_max=tnpc3->s*50;
//remove amulet of submission
if (tnpc3->neck){
if (tnpc3->neck->type==76) tnpc3->neck=NULL;
}
tnpc3->upflags|=1;
myobj3=OBJnew(); myobj3->type=87; myobj3->more2=0; myobj3->info=256; //orb of moons
additemroot(tnpc3,myobj3);
tplayer->GNPCflags[22]|=0xFFFFFFFF; //make all destinations available
txtset(t,"?"); t->d2[0]=22; NET_send(NETplayer,tplayer->net,t); //play endgame sequence!
tplayer->GNPCflags[18]|=16; //endgame sequence played!
}
}
}
goto finishuse;
}
/*
if (i==90){ //torch
if (i2==0) myobj->type=i+1*1024;
if (i2>=1) myobj->type=i;
goto finishuse;
}
*/
if (i==OBJ_PASSTHROUGH_V){ //v-passthrough
if (i2==0){
if (myobj->more==NULL)
{
myobj->more=OBJnew();
myobj2=(object*)myobj->more;
myobj2->more=myobj; //back link
myobj2->type=OBJ_PASSTHROUGH_V+1*1024;
OBJadd(myobj->x-1,myobj->y-1,myobj2);
}
else
{
OBJadd(myobj->x-1,myobj->y-1,(object*)myobj->more);
}
x=myobj->x;
y=myobj->y-1;
OBJremove(myobj);
myobj->type=OBJ_PASSTHROUGH_V+2*1024;
OBJadd(x,y,myobj);
goto finishuse;
}
else
{
if (i2==1){myobj2=myobj; myobj=(object*)myobj->more;}else{myobj2=(object*)myobj->more;}
if (myobj2!=NULL) OBJremove(myobj2);
x=myobj->x; y=myobj->y+1;
OBJremove(myobj);
myobj->type=OBJ_PASSTHROUGH_V;
OBJadd(x,y,myobj);
goto finishuse;
}
}
if (i==OBJ_PASSTHROUGH_H){ //h-passthrough
if (i2==0){
if (myobj->more==NULL)
{
myobj->more=OBJnew();
myobj2=(object*)myobj->more;
myobj2->more=myobj; //back link
myobj2->type=OBJ_PASSTHROUGH_H+1*1024;
OBJadd(myobj->x-1,myobj->y-1,myobj2);
}
else
{
OBJadd(myobj->x-1,myobj->y-1,(object*)myobj->more);
}
x=myobj->x-1;
y=myobj->y;
OBJremove(myobj);
myobj->type=OBJ_PASSTHROUGH_H+2*1024;
OBJadd(x,y,myobj);
goto finishuse;
}
else
{
if (i2==1){myobj2=myobj; myobj=(object*)myobj->more;}else{myobj2=(object*)myobj->more;}
if (myobj2!=NULL) OBJremove(myobj2);
x=myobj->x+1; y=myobj->y;
OBJremove(myobj);
myobj->type=OBJ_PASSTHROUGH_H;
OBJadd(x,y,myobj);
goto finishuse;
}
}
for (i4=297;i4<=300;i4++){
if (i==i4){ //oak door, ...
if (i2>=8){
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,"It's locked!"); NET_send(NETplayer,tplayer->net,t);
goto finishuse; //door is locked!
}
if (myobj->info&8) myobj=(object*)myobj->more; //<-
myobj2=(object*)myobj->more;
i2=myobj->type>>10;
if (i2&1) {myobj2=myobj; myobj=(object*)myobj->more;} else {myobj2=(object*)myobj->more;}
if (i2<4){
i2=i2>>1;
i2=i2<<1;
i2=i2&2;
myobj->type=i+((i2+4)*1024);
myobj2->type=i+((i2+5)*1024);
OBJcheckflags(myobj->x,myobj->y);
OBJcheckflags(myobj2->x,myobj2->y);
x2=myobj->x; y2=myobj->y;
i3=SFnew(x2,y2);
//i3 points to new sf
sf[i3].type=4;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=1.0f; //NULL
sf[i3].more=2;
goto finishuse;
}else{
i2=i2>>1;
i2=i2<<1;
i2=i2&2;
myobj->type=i+(i2*1024);
myobj2->type=i+((i2+1)*1024);
OBJcheckflags(myobj->x,myobj->y);
OBJcheckflags(myobj2->x,myobj2->y);
x2=myobj->x; y2=myobj->y;
i3=SFnew(x2,y2);
//i3 points to new sf
sf[i3].type=4;
sf[i3].x=x2;
sf[i3].y=y2;
sf[i3].wait=1.0f; //NULL
sf[i3].more=1;
goto finishuse;
} //<4
} //i==i4
} //i4 loop
useinventoryitem:
//if musical instrument is in inventory, then it can be used
if ((i==153)||(i==158)||(i==296)||(i==156)||(i==157)){ //panpipes, lute, xylophone, harpsichord, harp
//***assume proximity ok***
//set client in music mode with selected instrument
txtset(t,"??"); t->d2[0]=24;
if (i==153) t->d2[1]=3;
if (i==158) t->d2[1]=0;
if (i==296) t->d2[1]=4;
if (i==156) t->d2[1]=1;
if (i==157) t->d2[1]=2;
tplayer->instrument=t->d2[1];
tplayer->playinstrument=2;
NET_send(NETplayer,tplayer->net,t);
goto finishuse;
}
/*
//if musical instrument is in inventory, then it can be used
if ((i==153)||(i==158)||(i==296)){ //panpipes, lute, xylophone
//set client in music mode
goto finishuse;
}
*/
if (i==169){ //ducky
myobj3=tplayer->party[0];
i3=SFnew(myobj3->x,myobj3->y);
sf[i3].type=4; //sound
sf[i3].x=myobj3->x;
sf[i3].y=myobj3->y;
sf[i3].wait=1.0f; //NULL
sf[i3].more=5; //ducky
goto finishuse;
}
if (i==OBJ_GEM){ //gems
x3=10;
if (x3>255) x3=255; //cap
if (x3>tplayer->peer){
tplayer->peer=x3;
txtset(t,"??"); t->d2[0]=48; t->d2[1]=tplayer->peer; NET_send(NETplayer,tplayer->net,t);
}
if (myobj->more2!=1){ //more than 1!
myobj->more2--; goto finishuse;
}
OBJremove(myobj); OBJrelease(myobj);
myobj=NULL;
goto finishuse;
}
if (i==212){ //magic fan
x3=tplayer->windx; y3=tplayer->windy;
if ((x3==0)&&(y3==0)) {x3=windx; y3=windy;}
if ((x3==0)&&(y3==0)) {x3=0; y3=1; goto magicfan_used;}
if ((x3==0)&&(y3==1)) {x3=-1; y3=1; goto magicfan_used;}
if ((x3==-1)&&(y3==1)) {x3=-1; y3=0; goto magicfan_used;}
if ((x3==-1)&&(y3==0)) {x3=-1; y3=-1; goto magicfan_used;}
if ((x3==-1)&&(y3==-1)) {x3=0; y3=-1; goto magicfan_used;}
if ((x3==0)&&(y3==-1)) {x3=1; y3=-1; goto magicfan_used;}
if ((x3==1)&&(y3==-1)) {x3=1; y3=0; goto magicfan_used;}
if ((x3==1)&&(y3==0)) {x3=1; y3=1; goto magicfan_used;}
if ((x3==1)&&(y3==1)) {x3=0; y3=1; goto magicfan_used;}
magicfan_used:
tplayer->windx=x3; tplayer->windy=y3;
txtset(t,"??"); t->d2[0]=14; t->d2[1]=(tplayer->windx+1)+(tplayer->windy+1)*4; NET_send(NETplayer,tplayer->net,t);
goto finishuse;
}
if (i==93){ //sextant
//*sextants 304,360
myobj=tplayer->party[tplayer->selected_partymember];
x2=0;
if (myobj->y>=256) x2=2;
if (myobj->x<1024) x2=1;
if (x2){
if (x2==1){
x=(myobj->x+1024-304)/8; x-=128;
y=(myobj->y+1024-360)/8; y-=128;
}else{
x=((myobj->x-1024)+256-76)/2; x-=128;
y=((myobj->y-256)+256-90)/2; y-=128;
}
txtset(t,"?"); t->d2[0]=8;
txtnumint(t2,abs(y)); txtadd(t,t2);
if (y>0) txtadd(t,"'S, "); else txtadd(t,"'N, ");
txtnumint(t2,abs(x)); txtadd(t,t2);
if (x>0) txtadd(t,"'E"); else txtadd(t,"'W");
NET_send(NETplayer,tplayer->net,t);
}else{
txtset(t,"?Not usable here!"); t->d2[0]=8; NET_send(NETplayer,tplayer->net,t);
}
goto finishuse;
}
if (i==270){ //use balloon plans
//scan for required items
for (x6=0;x6<=7;x6++){ if (tplayer->party[x6]){
tnpc3=(npc*)tplayer->party[x6]->more;
x5=OBJlist((object*)tnpc3->items->more); //x5=last object number
}} //!=NULL,x6
OBJlist_last=NULL;
y7=0;
for(y6=0;y6<x5;y6++){
if ((OBJlist_list[y6]->type&1023)==421) y7|=1; //silk bag
if ((OBJlist_list[y6]->type&1023)==422) y7|=2; //basket
if ((OBJlist_list[y6]->type&1023)==284) y7|=4; //rope
if ((OBJlist_list[y6]->type&1023)==283) y7|=8; //anchor
if ((OBJlist_list[y6]->type&1023)==147) y7|=16; //cauldron
}
if (y7!=31){
txtset(t,"?Requires a balloon basket, a mammoth silk bag, rope, an anchor and a cauldron."); t->d2[0]=8; NET_send(NETplayer,tplayer->net,t);
goto finishuse;
}
//remove required items
for(y6=0;y6<x5;y6++){
if (((OBJlist_list[y6]->type&1023)==421)&&(y7&1)) {y7-=1; OBJremove(OBJlist_list[y6]);}
if (((OBJlist_list[y6]->type&1023)==422)&&(y7&2)) {y7-=2; OBJremove(OBJlist_list[y6]);}
if (((OBJlist_list[y6]->type&1023)==284)&&(y7&4)) {y7-=4; OBJremove(OBJlist_list[y6]);}
if (((OBJlist_list[y6]->type&1023)==283)&&(y7&8)) {y7-=8; OBJremove(OBJlist_list[y6]);}
if (((OBJlist_list[y6]->type&1023)==147)&&(y7&16)) {y7-=16; OBJremove(OBJlist_list[y6]);}
}
//add balloon to inventory (make sure it's a quest item)
myobj3=OBJnew(); myobj3->type=420; myobj3->info|=256; //quest item
tnpc3=(npc*)tplayer->party[0]->more;
additemroot(tnpc3,myobj3);
goto finishuse;
}
if (i==420){ //balloon
if (tplayer->craft==NULL){
if (usinghorse(tplayer)==NULL){
if ((tplayer->party[0]->x<1024)||((tplayer->party[0]->y>=256)&&(tplayer->party[0]->y<=512)&&(tplayer->party[0]->x<=1280) ) ){
if (tplayer->selected_partymember){ //change selected_partymember to 0
if (tplayer->party[tplayer->selected_partymember]){
tnpc3=(npc*)tplayer->party[tplayer->selected_partymember]->more;
if (tnpc3->order==0) tnpc3->order=1;
tnpc3->follow=tplayer->party[0];
}
tnpc3=(npc*)tplayer->party[0]->more;
if (tnpc3->order==1) tnpc3->order=0;
tnpc3->follow=tplayer->party[0];
tplayer->selected_partymember=0;
}//tplayer->selected_partymember
//remove item from inventory
myobj2=myobj; OBJremove(myobj2);
//create a balloon where the avatar is standing
myobj=tplayer->party[0]; x=myobj->x; y=myobj->y;
myobj2->type=423+1024*3; OBJadd(x,y,myobj2);
static mlobj *mmyobj; //array size varies
mmyobj=(mlobj*)malloc(sizeof(object*)*3);
myobj2->more=mmyobj;
myobj=OBJnew(); mmyobj->obj[0]=myobj; //middle
myobj->type=423+0*1024; myobj->info|=8; //<-base object
OBJadd(x-1,y-1,myobj); myobj->more=myobj2;
myobj=OBJnew(); mmyobj->obj[1]=myobj; //middle
myobj->type=423+1*1024; myobj->info|=8; //<-base object
OBJadd(x,y-1,myobj); myobj->more=myobj2;
myobj=OBJnew(); mmyobj->obj[2]=myobj; //middle
myobj->type=423+2*1024; myobj->info|=8; //<-base object
OBJadd(x-1,y,myobj); myobj->more=myobj2;
//use balloon (the one we just created :)
tplayer->craft_con=(object*)myobj2->more;
myobj2->more=tplayer->party[0]->more;
myobj2->info=tplayer->party[0]->info;
tplayer->craft=tplayer->party[0];
for (i4=7;i4>=0;i4--){
if (tplayer->party[i4]!=NULL){
OBJremove(tplayer->party[i4]);
VLNKremove(tplayer->party[i4]); VLNKsremove(tplayer->party[i4]);
tnpc3=(npc*)tplayer->party[i4]->more; tnpc3->target=NULL;
}
}
tplayer->party[0]=myobj2;
if (myobj2->info&32768) myobj2->info-=32768;
}//x,y
}//usinghorse
}//->craft==NULL
goto finishuse;
}
if (itemused==0){
myobj=NULL; goto retryuse;
}
if (itemused==1){
//No use-able object has been located on top, scan for items which may be used whilst not the top item
myobj=od[y][x];
lastchanceuse_loop:
i=myobj->type&1023;
myobj2=tplayer->party[0];
if (abs(myobj2->x-x)>1) goto lastchanceuse_playeronlyuse_skip;
if (abs(myobj2->y-y)>1) goto lastchanceuse_playeronlyuse_skip;
if (use_noladdercheck==0){
if ((i==305)||(i==326)||(i==308)) goto lastchanceuse_ladder;//ladder or dungeon or hole
}
lastchanceuse_playeronlyuse_skip:
if (myobj->next){ myobj=(object*)myobj->next; goto lastchanceuse_loop;}
}//itemused==1
finishuse:;
goto skip_pickup;
} //action==1
if (tplayer->action==2){ //look ->primary surface
x=tpx+tplayer->mx/32;
y=tpy+tplayer->my/32;
myobj=OBJfindlast(x,y);
if (myobj==NULL){
myobj=OBJfindlastall(x,y);
if (myobj==NULL) goto looknullobject;
}
if (myobj->info&8) myobj=(object*)myobj->more; //redirect!
if (myobj->type==51){ //force field
myobj2=(object*)myobj->prev;
if (tplayer->GNPCflags[3]&(1<<(myobj2->type>>10))) myobj=(object*)myobj->prev;
if (tplayer->GNPCflags[4]&(1<<(myobj2->type>>10))) myobj=(object*)myobj->prev;
}//force field
if ((myobj->type>=242)&&(myobj->type<=249)){ //skip rune LOOK
if (tplayer->GNPCflags[5]&(1<<(myobj->type-242))) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==(275+2*1024)){//yellow potion
if (myobj->info&256){//quest
if (tplayer->GNPCflags[32]&myobj->more2) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}//quest
}//yellow potion
if ((myobj->type>=400)&&(myobj->type<=407)){ //skip map(0-7) LOOK
if (tplayer->GNPCflags[7]&(1<<(myobj->type-400))) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==62){ //vortex cube SKIPLOOK
if ((myobj->x==1939)&&(myobj->y==57)){
if (tplayer->GNPCflags[6]&(1<<1)) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if ((myobj->x==923)&&(myobj->y==850)){
if ((tplayer->GNPCflags[18]&1)==0) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
}
if (myobj->type==389){ //silver tablet
if (tplayer->GNPCflags[6]&(1<<2)) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==390){ //silver tabletII
if (tplayer->GNPCflags[6]&(1<<3)) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==270){ //balloon plans
if (tplayer->GNPCflags[6]&(1<<4)) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==395){ //broken gargoyle lens
if (tplayer->GNPCflags[6]&(1<<5)) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj==nuggetsfix){ //nuggets
if ((tplayer->GNPCflags[6]&(1<<6))||(tplayer->online<1536)) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==59){ //codex
if (tplayer->GNPCflags[18]&8) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==394){ //brit lens SKIPLOOK
if ((tplayer->GNPCflags[18]&2)==0) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==396){ //garg lens SKIPLOOK
if ((tplayer->GNPCflags[18]&4)==0) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==416){ //nothing!
myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->type==173){ //trap
if ((myobj->info&(1<<9))==0) myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}
if (myobj->info&4){ //invisible crt
crt=(creature*)myobj->more;
if (crt->flags&2){
myobj=(object*)myobj->prev;
if (myobj==NULL) goto looknullobject;
}//2
}//4
for (x2=0;x2<=nresu;x2++){ //dead NPC? (only player who owns the dead npc can extract)
if (resu[x2]){
if (resu_body[x2]==myobj){
if (tplayer==resu_player[x2]){
//check if item is next to player
z2=0; for (z=0;z<=7;z++){
if (myobj2=tplayer->party[z]){
if (abs(myobj2->x-myobj->x)<=1){
if (abs(myobj2->y-myobj->y)<=1){
z2=1;
}}}}
if (z2==1){
x3=0;
tnpc=(npc*)resu[x2]->more;
leaveitems3:
if (myobj3=(object*)tnpc->items->more){
x3=1;
OBJremove(myobj3);
OBJadd(myobj->x,myobj->y,myobj3);
goto leaveitems3;
}
if (myobj3=tnpc->helm){ x3=1; tnpc->helm=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (myobj3=tnpc->neck){ x3=1; tnpc->neck=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (myobj3=tnpc->wep_left){ x3=1;
if (myobj3->type==(90+1024)) myobj3->type=90;
tnpc->wep_left=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (myobj3=tnpc->wep_right){ x3=1;
if (myobj3->type==(90+1024)) myobj3->type=90;
tnpc->wep_right=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (myobj3=tnpc->armour){ x3=1; tnpc->armour=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (myobj3=tnpc->ring_left){ x3=1; tnpc->ring_left=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (myobj3=tnpc->ring_right){ x3=1; tnpc->ring_right=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (myobj3=tnpc->boots){ x3=1; tnpc->boots=NULL; OBJadd(myobj->x,myobj->y,myobj3);}
if (x3){
tnpc->baseitem=tnpc->items; tnpc->baseitem_offset=0;
txtset(t,"?You search "); txtadd(t,tnpc->name); txtadd(t,"'s dead body."); t->d2[0]=8; NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
}//x3
}//z2
}
}
}
}
//if it is a container, retrieve items inside (if empty give stats)
if (myobj->more){
x2=myobj->type&1023;
x3=myobj->type>>10;
x4=0;
if ((obji[sprlnk[x2]].flags&1024)&&(x3==0)) x4=1;
if (x2==168) x4=1; //remains
if (x2==339) x4=1; //dead body
if (x2==176) x4=1; //drawers
if (x2==177) x4=1; //desk
if (x2==335) x4=1;
if (x2==134) x4=1; //carcass
if (x2==340) x4=1; //garg
if (x2==341) x4=1; //cyclops
if ((x2>=432)&&(x2<=447)) x4=1;
//other special cases?
if (x4==1){ //extract items out of container
//check if item is next to player
z2=0; for (z=0;z<=7;z++){
myobj2=tplayer->party[z];
if (myobj2!=NULL){
if (abs(myobj2->x-myobj->x)<=1){
if (abs(myobj2->y-myobj->y)<=1){
z2=1;
}} }}
if (z2==1){
if (myobj->more) OBJsave(myobj->x,myobj->y);
extractobj:
myobj2=(object*)myobj->more;
if (myobj2) {OBJremove(myobj2); myobj2->info|=112; OBJadd(myobj->x,myobj->y,myobj2); goto extractobj;}
goto skip_pickup;
}//z2
}//x4==1
}//->more
//f9=0;
inventory_look:
//if it's a player give a different description with their name
if (myobj->info&2){//npc
tnpc2=(npc*)myobj->more;
if (tnpc2->player){
tplayer2=(player*)tnpc2->player;
/*
if (tplayer2!=tplayer){//not a member of our party
if (tnpc2->port){
txtset(t5,"?"); t5->d2[0]=2;
txtset(t7,"??"); t7->ds[0]=1; txtadd(t5,t7);
t7->ds[0]=28; txtadd(t5,t7);//type=portrait look
t7->ds[0]=myobj->x; txtadd(t5,t7);
t7->ds[0]=myobj->y; txtadd(t5,t7);
t7->ds[0]=0; txtadd(t5,t7); //unused
t7->ds[0]=0; txtadd(t5,t7); //unused
t7->ds[0]=tnpc2->port; txtadd(t5,t7);//more=port
txtset(t7,"????"); t7->df[0]=1.0f; txtadd(t5,t7); //wait
NET_send(NETplayer,tplayer->net,t5);
}
}
*/
//send npc look message
/*
[44]
[portrait]
[length of name]
[name data(if any!)]
[1 byte value with bits indicating what is equipped]
order is:
helm,wep-right,wep-left,armour,boots,ring right, ring left,neck
2 bytes for type, and 1 byte for a plus value per item
*/
if (tnpc2->port){
txtsetchar(t5,44);
txtaddshort(t5,tnpc2->port);
//name is ALWAYS known for npcs with a ->player pointer
txtaddchar(t5,tnpc2->name->l);
txtadd(t5,tnpc2->name);
i3=0xFFFFFF;
if (tplayer2->party[0]==myobj){
i3=tplayer2->GNPCflags[245];
}
txtaddchar(t5,i3&0xFF);
txtaddchar(t5,(i3>>8)&0xFF);
txtaddchar(t5,(i3>>16)&0xFF);
txtset(t6,"");
i3=0;
i5=1;
for (i4=0;i4<8;i4++){
if (i4==0) myobj3=tnpc2->helm;
if (i4==1) myobj3=tnpc2->wep_right;
if (i4==2) myobj3=tnpc2->wep_left;
if (i4==3) myobj3=tnpc2->armour;
if (i4==4) myobj3=tnpc2->boots;
if (i4==5) myobj3=tnpc2->ring_right;
if (i4==6) myobj3=tnpc2->ring_left;
if (i4==7) myobj3=tnpc2->neck;
if (myobj3){
i3+=i5;
//type
txtaddshort(t6,myobj3->type);
//+ bonus
i6=ENHANCEget_attack(myobj3);
if (!i6) i6=ENHANCEget_defense(myobj3);
txtaddchar(t6,i6);
}//myobj3
i5<<=1;
}//i4
txtaddchar(t5,i3);
txtadd(t5,t6);
NET_send(NETplayer,tplayer->net,t5);
}//tnpc2->port
if (tplayer2->party[0]==myobj){
txtsetchar(t,8); txtaddchar(t,255);
txtadd(t,"Thou dost see ");
if (tplayer==tplayer2) {txtadd(t,"yourself."); goto skip_playername2;}
txtadd(t,tnpc2->name);
txtadd(t,". (Level ");
txtnumint(t2,tnpc2->lev); txtadd(t,t2);
i3=tnpc2->hp_max;
txtset(t2,")");
if (tnpc2->hp<i3) txtset(t2,", grazed)");
if (tnpc2->hp<(i3*4/5)) txtset(t2,", barely wounded)");
if (tnpc2->hp<(i3*3/5)) txtset(t2,", lightly wounded)");
if (tnpc2->hp<(i3*2/5)) txtset(t2,", heavily wounded)");
if (tnpc2->hp<(i3/5)) txtset(t2,", critically hurt)");
txtadd(t,t2);
skip_playername2:
goto skip_playername;
}
if (tnpc2->name){
//MUST BE A PARTY MEMBER!
txtsetchar(t,8); txtaddchar(t,255);
txtadd(t,"Thou dost see ");
txtadd(t,tnpc2->name);
txtadd(t,". (Level ");
txtnumint(t2,tnpc2->lev); txtadd(t,t2);
i3=tnpc2->hp_max;
txtset(t2,")");
if (tnpc2->hp<i3) txtset(t2,", grazed)");
if (tnpc2->hp<(i3*4/5)) txtset(t2,", barely wounded)");
if (tnpc2->hp<(i3*3/5)) txtset(t2,", lightly wounded)");
if (tnpc2->hp<(i3*2/5)) txtset(t2,", heavily wounded)");
if (tnpc2->hp<(i3/5)) txtset(t2,", critically hurt)");
txtadd(t,t2);
goto skip_playername;
}
}else{
//no player pointer npc!
//portrait look (non-player npc)
if (tnpc2->port){
txtsetchar(t5,44);
txtaddshort(t5,tnpc2->port);
//name is ALWAYS known for npcs with a ->player pointer
//txtaddchar(t5,tnpc2->name->l);
//txtadd(t5,tnpc2->name);
//set t6 to stock answer
i3=objname[(myobj->type&1023)*2];
i4=objname[(myobj->type&1023)*2+1];
txtNEWLEN(t6,i4);
memcpy(&t6->d2[0],&objname2[i3],i4);
//retrieve name if known
//to have a name they must have a converse number
if (i4=tnpc2->converse){
if (i4!=201){
if (i4==255) i4=0;//Dupre correction
if ((tplayer->NPCflags[i4]&256)>>8){
tfh=open(".\\host\\npcname.txt");
for (i3=0;i3<=i4;i3++){
txtfilein(t6,tfh);
}
close(tfh);
}
}else{
//201!
txtset(t6,tnpc2->name);
}
}
txtaddchar(t5,t6->l);
txtadd(t5,t6);
i3=0xFFFFFF;
txtaddchar(t5,i3&0xFF);
txtaddchar(t5,(i3>>8)&0xFF);
txtaddchar(t5,(i3>>16)&0xFF);
txtset(t6,"");
i3=0;
i5=1;
for (i4=0;i4<8;i4++){
if (i4==0) myobj3=tnpc2->helm;
if (i4==1) myobj3=tnpc2->wep_right;
if (i4==2) myobj3=tnpc2->wep_left;
if (i4==3) myobj3=tnpc2->armour;
if (i4==4) myobj3=tnpc2->boots;
if (i4==5) myobj3=tnpc2->ring_right;
if (i4==6) myobj3=tnpc2->ring_left;
if (i4==7) myobj3=tnpc2->neck;
if (myobj3){
i3+=i5;
//type
txtaddshort(t6,myobj3->type);
//+ bonus
i6=ENHANCEget_attack(myobj3);
if (!i6) i6=ENHANCEget_defense(myobj3);
txtaddchar(t6,i6);
}//myobj3
i5<<=1;
}//i4
txtaddchar(t5,i3);
txtadd(t5,t6);
NET_send(NETplayer,tplayer->net,t5);
}//tnpc2->port
/*
if (tnpc2->port){
txtset(t5,"?"); t5->d2[0]=2;
txtset(t7,"??"); t7->ds[0]=1; txtadd(t5,t7);
t7->ds[0]=28; txtadd(t5,t7);//type=portrait look
t7->ds[0]=myobj->x; txtadd(t5,t7);
t7->ds[0]=myobj->y; txtadd(t5,t7);
t7->ds[0]=0; txtadd(t5,t7); //unused
t7->ds[0]=0; txtadd(t5,t7); //unused
t7->ds[0]=tnpc2->port; txtadd(t5,t7);//more=port
txtset(t7,"????"); t7->df[0]=1.0f; txtadd(t5,t7); //wait
NET_send(NETplayer,tplayer->net,t5);
}
*/
}
}
//have object
//create a description & send a message
//txtset(t,"?");
//t->d2[0]=8;
txtsetchar(t,8); txtaddchar(t,255);
//t2<-object name
x2=objname[(myobj->type&1023)*2];
x3=objname[(myobj->type&1023)*2+1];
txtNEWLEN(t2,x3);
memcpy(&t2->d2[0],&objname2[x2],x3);
txtset(t3,"dead body");
if (txtsame(t2,t3)){
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_body[i3]==myobj){
tnpc2=(npc*)resu[i3]->more;
txtset(t2,"Thou dost see ");
txtadd(t2,tnpc2->name);
goto gotgrammar;
}
}
}
}
//check for crt pointer
if (myobj->info&4){
crt2=(creature*)myobj->more;
//horse (owned by a player)
if ((myobj->type&1023)==430){
if (crt2->flags&128){
txtset(t,"?");
txtsetchar(t,8); txtaddchar(t,255);
txtadd(t,"Thou dost see ");
horsepaperslook_getmoreinfo:
if (crt2->respawn_y==0xFFFF){
txtadd(t,"a ");
}else{
if (playerlist[crt2->respawn_y]){ if (playerlist[crt2->respawn_y]->net){ if (myobj2=getprimarypartymemberobj(playerlist[crt2->respawn_y])){
txtadd(t,((npc*)myobj2->more)->name);
txtadd(t,"'s ");
goto houselook_foundownersname;
}}}
txtadd(t,"a ");
}
houselook_foundownersname:
//grain state
if (((crt2->respawn_x>>4)&3)==3) txtadd(t,"full horse ");
if (((crt2->respawn_x>>4)&3)==2) txtadd(t,"well fed horse ");
if (((crt2->respawn_x>>4)&3)==1) txtadd(t,"hungry horse ");
if (((crt2->respawn_x>>4)&3)==0) txtadd(t,"starving horse ");
//horseshoes state
if (((crt2->respawn_x>>6)&3)==3) txtadd(t,"with new horseshoes");
if (((crt2->respawn_x>>6)&3)==2) txtadd(t,"with good horseshoes");
if (((crt2->respawn_x>>6)&3)==1) txtadd(t,"with reasonable horseshoes");
if (((crt2->respawn_x>>6)&3)==0) txtadd(t,"with worn horseshoes");
if (crt2->respawn_x&15){
txtnumint(t2,crt2->respawn_x&15);
txtadd(t,", it has won ");
txtadd(t,t2);
if ((crt2->respawn_x&15)==1) txtadd(t," race!"); else txtadd(t," races!");
}else{
txtadd(t,".");
}
goto skiphorsewithowner;
}
}
i3=(obji[sprlnk[myobj->type&1023]].v8>>8)*4;
txtset(t5,t2);
txtset(t2,"");
if (crt2->hp<i3) txtset(t2,"grazed ");
if (crt2->hp<(i3*4/5)) txtset(t2,"barely wounded ");
if (crt2->hp<(i3*3/5)) txtset(t2,"lightly wounded ");
if (crt2->hp<(i3*2/5)) txtset(t2,"heavily wounded ");
if (crt2->hp<(i3/5)) txtset(t2,"critically hurt ");
txtadd(t2,t5);
}
if (myobj->type==78){ //staff
txtset(t2,"");
if (myobj->more2&65535){
txtset(t3,spellname[myobj->more2&65535]);
txtlcase(t3);
txtadd(t2,t3);
txtadd(t2," ");
}
txtadd(t2,"staff");
if (myobj->more2&65535){
txtadd(t2," (x");
txtnumint(t3,myobj->more2>>16);
txtadd(t2,t3);
txtadd(t2,")");
}
}
if (myobj->type==81){
txtset(t2,"new");
if (myobj->more2!=0) txtset(t2,"barely used");
if (myobj->more2>=512) txtset(t2,"worn");
if (myobj->more2>=1024) txtset(t2,"old");
txtadd(t2," storm cloak");
}
if ((myobj->type&1023)==98){
i3=myobj->type>>10;
if (i3==0) txtset(t2,"open chest");
if (i3==2) txtset(t2,"locked chest");
if (i3==3) txtset(t2,"magically locked chest");
}
i3=myobj->type&1023;
if ((i3>=297)&&(i3<=300)){
txtset(t5,t2);
i3=myobj->type>>12;
if (i3==0) txtset(t2,"open ");
if (i3==1) txtset(t2,"");
if (i3==2) txtset(t2,"locked ");
if (i3==3) txtset(t2,"magically locked ");
txtadd(t2,t5);
}//i3
//check if it's a spell
txtset(t3,"spell");
if (txtsame(t2,t3)){
//txtset(t3,
txtset(t2,spellname[myobj->more2]);
txtlcase(t2);
txtadd(t2," spell");
}
txtset(t3,"fire wand");
if (txtsame(t2,t3)){
//txtset(t3,
txtset(t2,"new");
if (myobj->more2!=0) txtset(t2,"smoldering");
if (myobj->more2>=64) txtset(t2,"flaming");
if (myobj->more2>=192) txtset(t2,"blazing");
txtadd(t2," fire wand");
}
txtset(t3,"lightning wand");
if (txtsame(t2,t3)){
//txtset(t3,
txtset(t2,"new");
if (myobj->more2!=0) txtset(t2,"glowing");
if (myobj->more2>=64) txtset(t2,"sparkling");
if (myobj->more2>=192) txtset(t2,"brilliant");
txtadd(t2," lightning wand");
}
txtset(t3,"invisibility ring");
if (txtsame(t2,t3)){
txtset(t2,"new");
if (myobj->more2!=0) txtset(t2,"glowing");
if (myobj->more2>=64) txtset(t2,"shining");
if (myobj->more2>=192) txtset(t2,"brilliant");
txtadd(t2," invisibility ring");
}
txtset(t3,"regeneration ring");
if (txtsame(t2,t3)){
txtset(t2,"new");
if (myobj->more2!=0) txtset(t2,"glowing");
if (myobj->more2>=32) txtset(t2,"shining");
if (myobj->more2>=96) txtset(t2,"brilliant");
txtadd(t2," regeneration ring");
}
txtset(t3,"protection ring");
if (txtsame(t2,t3)){
txtset(t2,"new");
if (myobj->more2!=0) txtset(t2,"glowing");
if (myobj->more2>=1024) txtset(t2,"shining");
if (myobj->more2>=3072) txtset(t2,"brilliant");
txtadd(t2," protection ring");
}
txtset(t3,"torch");
if (txtsame(t2,t3)){
x3=(myobj->info>>9)&15;
txtset(t2,"new");
if (x3!=0) txtset(t2,"old");
if (x3>=4) txtset(t2,"half used");
if (x3>=12) txtset(t2,"almost new");
txtadd(t2," torch");
if (myobj->more2>1) txtadd(t2,"e");
}
txtset(t3,"ship deed");
if (txtsame(t2,t3)){
if (myobj->info&(1<<9)) txtset(t2,"skiff deed"); else txtset(t2,"ship deed");
}
if (myobj->type==OBJ_TMAP){ //treasure map
x5=(myobj->more2)&1023;
y2=(myobj->more2>>10)&1023;
x6=(myobj->more2>>20)&7;
y3=(myobj->more2>>23)&7;
x4=(myobj->more2>>26)&7;
y4=(myobj->more2>>29)&7;
x5+=(x6-3)*2;
if(x5<0) {x5=0;}
if(x5>=1024) {x5=1023;}
y2+=(y3-3)*2;
if(y2<0) {y2=0;}
if(y2>=1024) {y2=1023;}
txtset(t8,"?");
t8->d2[0]=49;
txtset(t9,"????");
t9->dl[0]=(x5+1024*y2+1024*1024*x4+1024*1024*8*y4);
txtadd(t8,t9);
NET_send(NETplayer,tnpc->player->net,t8);
}
//apply grammar rules // luteijn Original uses special flags for this!
//exceptions
if ((myobj->type&1023)==409) {txtadd(t,"Thou dost see "); goto gotgrammar;} //LB
if ((myobj->type&1023)==360) {txtadd(t,"Thou dost see "); goto gotgrammar;} //rot worms
if ((myobj->type&1023)==343) {txtadd(t,"Thou dost see "); goto gotgrammar;} //insects
if ((myobj->type&1023)==375) {txtadd(t,"Thou dost see "); goto gotgrammar;} //slime
if ((myobj->type&1023)==135) {txtadd(t,"Thou dost see "); goto gotgrammar;} //horse chops
//monsters
if (obji[sprlnk[myobj->type&1023]].v4) goto amonster;
//nc non-countable
if (obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].v6&1){
txtadd(t,"Thou dost see "); goto gotgrammar;
}
if (obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].flags&4096){ //multiple
if (myobj->more2>1){
txtadd(t,"Thou dost see ");
txtnumint(t3,myobj->more2);
txtadd(t,t3);
txtadd(t," ");
//of-> +s of
txtset(t3," of ");
if (x2=txtsearch(t2,t3)){
txtset(t3,t2); txtleft(t3,x2-1);
if ((myobj->type&1023)==128) txtset(t3,"loave"); //loaf->loaves
txtset(t4,t2); txtright(t4,t2->l-x2+1);
txtadd(t3,"s"); txtadd(t3,t4); txtset(t2,t3);
goto gotgrammar;
}
//default: +s
txtadd(t2,"s");
goto gotgrammar;
}//>1
}//multiple
amonster:
//the + CAPITAL LETTER
x2=t2->d2[0];
if ((x2>=65)&&(x2<=90)) {txtadd(t,"Thou dost see the "); goto gotgrammar;}
// vowel?
x3=0;
if (x2==97) x3=1; //a
if (x2==101) x3=1; //e
if (x2==105) x3=1; //i
if (x2==111) x3=1; //o
if (x2==117) x3=1; //u
if (x3) {txtadd(t,"Thou dost see an "); goto gotgrammar;}
txtadd(t,"Thou dost see a ");
gotgrammar:
txtadd(t,t2);
x2=ENHANCEget_attack(myobj); if (!x2) x2=ENHANCEget_defense(myobj);
if (x2){
txtadd(t," +");
txtnumint(t2,x2);
txtadd(t,t2);
}
if ((myobj->type&1023)==OBJ_POCKET_WATCH && myobj->more2!=0) { //different construction phases in the quest
if (myobj->more2==1) {
txtadd(t," mold");
}
if (myobj->more2==2) {
txtadd(t," frame");
}
if (myobj->more2==3) {
txtadd(t," that is missing the glass crystal");
}
if (myobj->more2==4) {
txtadd(t," that is almost done");
}
}
f=WTfind(myobj);
f9=f;
if (f){
txtadd(t,", weighing ");
x2=f/100;
txtnumint(t2,x2);
txtadd(t,t2);
if ((float)x2!=(f/100.0f)){
txtadd(t,".");
txtnumint(t2,(int)f%100);
if (t2->l==1) txtadd(t,"0");
if (t2->l==2){
if (t2->d2[1]==48) txtleft(t2,1);
}
txtadd(t,t2);
}
if (f==1.0f) txtadd(t," stone"); else txtadd(t," stones");
}
if (myobj->type==448){//horse papers
txtadd(t,", for ");
myobj=(object*)myobj->more; crt2=(creature*)myobj->more;
goto horsepaperslook_getmoreinfo;
}
txtadd(t,".");
if ((obji[sprlnk[myobj->type&1023]].v1)&&(obji[sprlnk[myobj->type&1023]].v2)){
txtadd(t," It can do ");
x2=obji[sprlnk[myobj->type&1023]].v1+ENHANCEget_attack(myobj);
txtnumint(t2,x2);
txtadd(t,t2);
txtadd(t," and absorb ");
x2=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
txtnumint(t2,x2);
txtadd(t,t2);
if (x2==1) txtadd(t," point of damage"); else txtadd(t," points of damage");
txtadd(t,".");
goto complex_done;
}
if (obji[sprlnk[myobj->type&1023]].v1){
txtadd(t," It can do ");
x2=obji[sprlnk[myobj->type&1023]].v1+ENHANCEget_attack(myobj);
txtnumint(t2,x2);
txtadd(t,t2);
if (x2==1) txtadd(t," point of damage"); else txtadd(t," points of damage");
txtadd(t,".");
}
if (obji[sprlnk[myobj->type&1023]].v2+ ENHANCEget_defense(myobj)){
if ((myobj->type&1023)==27) txtadd(t," They can absorb "); else txtadd(t," It can absorb "); //boots exception
x2=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
txtnumint(t2,x2);
txtadd(t,t2);
if (x2==1) txtadd(t," point of damage"); else txtadd(t," points of damage");txtadd(t,".");
}
complex_done:
//if ((ol[i].type&1)==0) myobj->info|=128; //128 1=stealing, 0=ok to take
if (myobj->info&128){
if (f9){ //has weight
txtadd(t," Taking this is stealing!");
}
}
if (myobj->info&256){
if (f9){ //has weight
txtadd(t," This is a quest item!");
}
}
if (myobj->type==OBJ_SUNDIAL){ //sundial
if ((btime>5)&&(btime<20)) goto thetimeis;
}
if ((myobj->type&1023)==OBJ_CLOCK || ((myobj->type&1023)==OBJ_POCKET_WATCH && myobj->more2==0)){ //clock
thetimeis:
txtadd(t," The time is ");
x=btime;
x2=(btime-(float)x)*60.0f;
if (x>12) x-=12;
if (x==0) x=12;
txtnumint(t2,x);
txtadd(t,t2);
txtadd(t,":");
txtnumint(t2,x2);
if (t2->l==1) txtadd(t,"0");
txtadd(t,t2);
if (btime>=12.0f) txtadd(t," P.M."); else txtadd(t," A.M.");
}
//txtadd(t,".");
skiphorsewithowner:
skip_playername:
NET_send(NETplayer,tplayer->net,t);
//sign //scroll //picture //book //gsign //codex //circles //tombstone //cross
if (((myobj->type&1023)==332)||((myobj->type&1023)==152)||((myobj->type&1023)==143)||((myobj->type&1023)==151)||((myobj->type&1023)==333)||((myobj->type&1023)==59)||((myobj->type&1023)==61)||((myobj->type&1023)==254)||((myobj->type&1023)==255)){
if (myobj->more2){
if (myobj->more2&65536){//house sign!
x2=myobj->more2&65535;
if (housesav[x2].flags&1){//occupied
txtset(t,"?"); txtset(t3,"");
for (x3=0;x3<=31;x3++){
if (housesav[x2].charactername[x3]){t->d2[0]=housesav[x2].charactername[x3]; txtadd(t3,t);}
}
txtadd(t3,"'s House");
if (x2==47&&(myobj->x)!=79) txtadd(t3,"\\Beware of the drakes!");
goto housesign;
}
txtset(t3,"For Sale\\No.");
txtnumint(t4,x2);
txtadd(t3,t4);
if (x2==47&&(myobj->x)!=79) txtadd(t3,"\\Beware of the drakes!");
goto housesign;
}
x2=tsign[(myobj->more2-1)*2];
x3=tsign[(myobj->more2-1)*2+1];
txtNEWLEN(t,x3);
memcpy(&t->d2[0],&tsign2[x2],x3);
txtset(t3,t);
//1garg 2normal 3runes
txtset(t,"?"); t->d2[0]=2; if (x=txtsearch(t3,t)){
if (tnpc->player->GNPCflags[9]){
txtset(t,t3); txtleft(t3,x-1); txtright(t,t->l-x); txtadd(t3,t);
}else{
txtleft(t3,x-2);
}
}//2
housesign:
//edit t3?
//MessageBox(NULL,t3->d,"Ultima 6 Online",MB_OK);
//create PRIVATE sfx message
txtset(t,"?"); t->d2[0]=2;
txtset(t2,"??"); t2->ds[0]=1; txtadd(t,t2);
t2->ds[0]=3; txtadd(t,t2);
t2->ds[0]=myobj->x-1;
if (myobj->x==0) t2->ds[0]=tnpc->player->party[tnpc->player->selected_partymember]->x-1;
txtadd(t,t2);
t2->ds[0]=myobj->y-1;
if (myobj->y==0) t2->ds[0]=tnpc->player->party[tnpc->player->selected_partymember]->y-1;
txtadd(t,t2);
t2->ds[0]=t3->l; txtadd(t,t2);
t2->ds[0]=0; txtadd(t,t2); //unused
t2->ds[0]=187; txtadd(t,t2); //more=port blank!
txtset(t2,"????"); t2->df[0]=2; txtadd(t,t2); //wait
txtadd(t,t3);
NET_send(NETplayer,tplayer->net,t);
}
}
/*
if (t->d2[0]==8){ //set mouse object
exit2(8);
goto CLIENT_donemess;
}
*/
goto skip_pickup;
looknullobject:; //2003: skip null objects
//report info about the basetile being looked at
x2=bt[y][x]&1023;
if (x2==0) goto skip_pickup;//nothing!
if (x2==1) txtset(t,"grass");
if (x2>=2) txtset(t,"swamp");
if (x2>=5) txtset(t,"a shrub");
if (x2>=6) txtset(t,"a bush");
if (x2>=8) txtset(t,"water");
if (x2>=16) txtset(t,"shore");
if (x2>=48) txtset(t,"a tree");
if (x2>=52) txtset(t,"grass");
if (x2>=64) txtset(t,"a tree");
if (x2>=72) txtset(t,"a dead tree");
if (x2>=73) txtset(t,"scrub");
if (x2>=78) txtset(t,"a shrub");
if (x2>=79) txtset(t,"earth");
if (x2>=96) txtset(t,"an embankment");
if (x2>=108) txtset(t,"earth");
if (x2>=112) txtset(t,"a mountain");
if (x2>=125) txtset(t,"snowcaps");
if (x2>=140) txtset(t,"a wall");
if (x2>=188) txtset(t,"a field");
if (x2>=189) txtset(t,"crops");
if (x2>=192) txtset(t,"an arrow slit");
if (x2>=196) txtset(t,"a window");
if (x2>=198) txtset(t,"a crenellation");
if (x2>=200) txtset(t,"a window");
if (x2==206) goto skip_pickup;//nothing!
if (x2>=207) txtset(t,"a wall");
if (x2>=208) txtset(t,"the floor");
if (x2>=217) txtset(t,"wet earth");
if (x2>=218) txtset(t,"a puddle");
if (x2>=219) txtset(t,"a pool");
if (x2>=220) txtset(t,"the floor");
if (x2>=221) txtset(t,"lava");
if (x2>=224) txtset(t,"a pyramid");
if (x2>=240) txtset(t,"an earthen wall");
if (x2>=252) txtset(t,"the ethereal void");
if (x2>=256) goto skip_pickup;//nothing!
txtset(t2,"Thou dost see "); txtadd(t2,t); txtadd(t2,".");
txtsetchar(t,8); txtaddchar(t,255); txtadd(t,t2);
NET_send(NETplayer,tplayer->net,t);
goto skip_pickup;
} //action==2 look
if (tplayer->action==3){ //attack
if (tplayer->craft){
if ((tplayer->party[0]->type&1023)==412){ //ship
goto shipattack;
}
}
if (tplayer->craft==NULL){
shipattack:
x=tpx+tplayer->mx/32;
y=tpy+tplayer->my/32;
myobj=OBJfindlast(x,y);
if (myobj!=NULL){
//is it a member of our party? if so break off combat
//for (x2=0;x2<=7;x2++){
//if (tplayer->party[x2]==myobj){
if (myobj->info&2){ //if NPC break off combat
for (x2=0;x2<=7;x2++){
if (tplayer->party[x2]){
VLNKsremove(tplayer->party[x2]);
tnpc2=(npc*)tplayer->party[x2]->more;
tnpc2->target=NULL;
tnpc2->order=3; if (x2==tplayer->selected_partymember) tnpc2->order=0;
}//->party
}//x2
goto skip_pickup;
}
//}
//}
if (myobj->info&8) myobj=(object*)myobj->more; //redirect
if (myobj->info&4){ //<-crt
//myobj2=tplayer->party[0];
//tnpc=(npc*)myobj2->more;
//tnpc->order=3;
//tnpc->target=myobj;
//set other party members to attack as well
for (x2=0;x2<=7;x2++){
if (tplayer->party[x2]){
myobj2=tplayer->party[x2];
tnpc=(npc*)myobj2->more;
tnpc->order=3;
tnpc->target=myobj;
VLNKsremove(myobj2); //remove prev vlnk
VLNKnew(myobj2,myobj,(unsigned long)&tnpc->target); //add vlnk
if (tplayer->craft) goto shipattack2; //exit loop after processing party[0]
}
}
} //<-crt
shipattack2:
//attack item (locked chest, door, spider web, other breakable items) (lets take spider web as an example)
if ((myobj->type&1023)==OBJ_CHEST) goto targetitem;
if (myobj->type==OBJ_WEB){ //web
targetitem:
myobj2=tplayer->party[tplayer->selected_partymember];
tnpc=(npc*)myobj2->more;
tnpc->order=3;
tnpc->target=myobj;
VLNKsremove(myobj2); //remove prev vlnk
VLNKnew(myobj2,myobj,(unsigned long)&tnpc->target); //add vlnk
}
} //!=NULL
//set creature as a target for attack oh no! it's gonna die
//unsigned char order;
//0=none
//1=follow party leader
//2=schedule
//3=attack target
}//craft
goto skip_pickup;
} //action==3 attack
} //primary surface click
if (tplayer->mf<=7){ if (tplayer->party[tplayer->mf]){
//2003 Xtnpc=(npc*)activeplayer->party[tplayer->mf]->more;
tnpc=(npc*)tplayer->party[tplayer->mf]->more;
if (tplayer->key&KEYmbclick){
//tnpc->upflags|=(32+64); //inv+eqp
//tnpc->update=1;
//clicked on opened "bag" icon ->close bag
if ((tplayer->mx>=(90))&&(tplayer->my>=(128+3))&&(tplayer->mx<((90)+32))&&(tplayer->my<((128+3)+32))){
if (tnpc->baseitem!=tnpc->items){ //backwards traverse
myobj2=tnpc->baseitem;
myobj=(object*)tnpc->baseitem->prev;
getprev10:
//TROLL GPF NEXT LINE (BACKSCANNING THROUGH INVENTORY?)
if ((myobj->more!=myobj2)||((obji[sprlnk[myobj->type&1023]].flags&1024)==0)) {myobj2=myobj; myobj=(object*)myobj->prev; goto getprev10;}
tnpc->baseitem=myobj;
tnpc->baseitem_offset=0;
tnpc->upflags|=32;
goto skip_pickup;
}
}//x,y
if (tplayer->action==0){
//scroll inventory down
if ((tplayer->mx>=(111-3))&&(tplayer->my>=(228-3))){
if ((tplayer->mx<=(121+3))&&(tplayer->my<=(243+3))){
tnpc->upflags|=32;
//is scroll down available?
myobj=(object*)tnpc->baseitem;
myobj=(object*)myobj->more;
x=61; y=61; x3=tnpc->baseitem_offset;
dniz:
if (myobj!=NULL){
if (x3>0) {x3--;goto skipbio1z;}
x=x+16;
if (x>109) {x=61;y=y+16;}
if (y>109){
if (myobj->next!=NULL)
{
tnpc->baseitem_offset+=4;
}
goto diskipz;
}
if (myobj->next!=NULL){
skipbio1z:
myobj=(object*)myobj->next;
goto dniz;
}
}
diskipz:;
goto skip_pickup;
}}
//scroll inventory up
if ((tplayer->mx>=(111-3))&&(tplayer->my>=(197-3))){ if ((tplayer->mx<=(121+3))&&(tplayer->my<=(212+3))){
if (tnpc->baseitem_offset>=4) {tnpc->baseitem_offset-=4;}else{tnpc->baseitem_offset=0;}
tnpc->upflags|=32;
goto skip_pickup;
}}
if ((tplayer->mx>=122)&&(tplayer->my>=122)){
x=(tplayer->mx-122)/32;
y=(tplayer->my-122)/32;
i2=x+(y*4);
myobj=tnpc->baseitem;
myobj=(object*)myobj->more;
i3=tnpc->baseitem_offset;
fo2:
if (i3>0){i3--;myobj=(object*)myobj->next;goto fo2;}
if (myobj!=NULL){
if (i2>0){
if (myobj->next!=NULL){
myobj=(object*)myobj->next;
i2--;
goto fo2;
}else{myobj=NULL;}
}
if (myobj){
if (tplayer->key&KEYquan){
if (tplayer->quan){
if (obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].flags&4096){
if (tplayer->quan<myobj->more2){
myobj2=OBJnew();
myobj2->type=myobj->type;
myobj2->info=myobj->info;
myobj2->more2=tplayer->quan;
myobj->more2-=tplayer->quan;
tplayer->mobj=myobj2;
goto nopickup2;
}//<
}//multiple
}//->quan
}//KEYquan
}
tplayer->mobj=myobj;
if (tplayer->mobj!=NULL) OBJremove(tplayer->mobj);
nopickup2:
tnpc->upflags|=32;
}
} //inventory block
else
{ //click outside inventory
//2003: new position pickup (no mouse object)
x2=tplayer->mx; y2=tplayer->my;
x3=helmx; y3=helmy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
tplayer->mobj=tnpc->helm;
tnpc->helm=NULL;
tnpc->upflags|=64;
goto mobj_gotitem;
}
x3=wep_rightx; y3=wep_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
tplayer->mobj=tnpc->wep_right;
tnpc->wep_right=NULL;
if (tplayer->mobj){
//if ((tplayer->mobj->type&1023)==258) {tnpc->flags&=(255-2);} //invisibility ring
if ((tplayer->mobj->type&1023)==90) {tplayer->mobj->type=90;}
if (tplayer->mobj->type==57){ //unready spellbook
tnpc->upflags|=128;
}
}
tnpc->upflags|=64;
goto mobj_gotitem;
}
x3=wep_leftx; y3=wep_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
tplayer->mobj=tnpc->wep_left;
tnpc->wep_left=NULL;
if (tplayer->mobj){
//if ((tplayer->mobj->type&1023)==258) {tnpc->flags&=(255-2);} //invisibility ring
if ((tplayer->mobj->type&1023)==90) {tplayer->mobj->type=90;}
if (tplayer->mobj->type==57){ //unready spellbook
tnpc->upflags|=128;
}
}
tnpc->upflags|=64;
goto mobj_gotitem;
}
x3=armourx; y3=armoury;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
tplayer->mobj=tnpc->armour;
tnpc->armour=NULL;
tnpc->upflags|=64;
goto mobj_gotitem;
}
x3=bootsx; y3=bootsy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
tplayer->mobj=tnpc->boots;
tnpc->boots=NULL;
tnpc->upflags|=64;
goto mobj_gotitem;
}
x3=neckx; y3=necky;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (tnpc->neck){
if (tnpc->neck->type==76){
txtset(t,"?"); t->d2[0]=8; txtadd(t,"Magical energy prevents you from removing the amulet!"); NET_send(NETplayer,tplayer->net,t);
goto mobj_gotitem;
}
}
tplayer->mobj=tnpc->neck;
tnpc->neck=NULL;
tnpc->upflags|=64;
goto mobj_gotitem;
}
x3=ring_leftx; y3=ring_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
tplayer->mobj=tnpc->ring_left;
tnpc->ring_left=NULL;
tnpc->upflags|=64;
goto mobj_gotitem;
}
x3=ring_rightx; y3=ring_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
tplayer->mobj=tnpc->ring_right;
tnpc->ring_right=NULL;
tnpc->upflags|=64;
goto mobj_gotitem;
}
mobj_gotitem:;
} //else outside inventory
} //action==0
if (tplayer->action==2){ //look, opens inventory container items
tnpc->upflags|=32;
if ((tplayer->mx>=122)&&(tplayer->my>=122)){
x=(tplayer->mx-122)/32;
y=(tplayer->my-122)/32;
i2=x+(y*4);
myobj=tnpc->baseitem;
myobj=(object*)myobj->more;
i3=tnpc->baseitem_offset;
fo2b:
if (i3>0){i3--;myobj=(object*)myobj->next;goto fo2b;}
if (myobj!=NULL){
if (i2>0){
if (myobj->next!=NULL){
myobj=(object*)myobj->next;
i2--;
goto fo2b;
}else{myobj=NULL;}
}
}
if (myobj){
if ((myobj->type==(98+1024*2))||(myobj->type==(98+1024*3))) goto inventory_look; //magically/locked chests
for (i3=0;i3<=nresu;i3++){
if (resu[i3]){
if (resu_body[i3]==myobj){
goto inventory_look; //block looking inside resurrectable bodies
}}}
if (obji[sprlnk[myobj->type&1023]].flags&1024){ //2003: check container flag
tnpc->baseitem=myobj;
tnpc->baseitem_offset=0;
goto inventory_look;
//goto skip_pickup;
}
goto inventory_look;
}//myobj
goto skip_pickup;
} //if x&y
//what about equipped items?
x2=tplayer->mx; y2=tplayer->my;
x3=helmx; y3=helmy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->helm) goto inventory_look;
}
x3=wep_rightx; y3=wep_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->wep_right) goto inventory_look;
}
x3=wep_leftx; y3=wep_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->wep_left) goto inventory_look;
}
x3=armourx; y3=armoury;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->armour) goto inventory_look;
}
x3=bootsx; y3=bootsy;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->boots) goto inventory_look;
}
x3=neckx; y3=necky;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->neck) goto inventory_look;
}
x3=ring_leftx; y3=ring_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->ring_left) goto inventory_look;
}
x3=ring_rightx; y3=ring_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->ring_right) goto inventory_look;
}
goto skip_pickup;
} //action==2
if (tplayer->action==1){ //use inventory item
tnpc->upflags|=32;
if ((tplayer->mx>=122)&&(tplayer->my>=122)){
x=(tplayer->mx-122)/32;
y=(tplayer->my-122)/32;
i2=x+(y*4);
myobj=tnpc->baseitem;
myobj=(object*)myobj->more;
i3=tnpc->baseitem_offset;
fo2d:
if (i3>0){i3--;myobj=(object*)myobj->next;goto fo2d;}
if (myobj!=NULL){
if (i2>0){
if (myobj->next!=NULL){
myobj=(object*)myobj->next;
i2--;
goto fo2d;
}else{myobj=NULL;}
}
}
if (myobj!=NULL){
itemused=2; i=myobj->type&1023; i2=myobj->type>>10; goto useinventoryitem;
}
}//if x&y
//use staff //staff use
x2=tplayer->mx; y2=tplayer->my;
x3=wep_rightx; y3=wep_righty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->wep_right){
if (myobj->type==78) goto staff_use0;
}
}
x3=wep_leftx; y3=wep_lefty;
if ((x2>=x3)&&(y2>=y3)&&(x2<(x3+32))&&(y2<(y3+32))){
if (myobj=tnpc->wep_left){
if (myobj->type==78) goto staff_use0;
}
}
myobj=NULL;
staff_use0:
if (myobj){
if (myobj->more2>>16){
txtset(t,"?"); t->d2[0]=23; //staff cast
txtset(t2,"??"); t2->ds[0]=myobj->more2&65535; txtadd(t,t2); //spell type
NET_send(NETplayer,tplayer->net,t);
tplayer->staffcast_npc=tplayer->party[tplayer->mf]; //object* of npc using the staff
tplayer->staffcast_staff=myobj; //object* of staff
}//num. spells !=0
}//myobj
goto skip_pickup;
}//use inventory item
} //mbclick
} //valid mf value
} //mf<=7
skip_pickup:;
}//check if player is alive and selected party member is valid
}//current player
}//player INPUT update (HOST controlled)
//2003: send NPC-frame update message to client
for (tpl=0;tpl<=playerlist_last;tpl++){
if (playerlist[tpl]){ //current player
if (playerlist[tpl]->net!=NULL){ //net connection exists
//2003: mobj update (this should be incorporated into the NPC update message if possible)
if (playerlist[tpl]->mobj!=playerlist[tpl]->mobj_last){
txtset(t,"?");
txtset(t2,"??");
t->d2[0]=4;
if (playerlist[tpl]->mobj!=NULL){
t2->ds[0]=playerlist[tpl]->mobj->type;
}else{t2->ds[0]=0xFFFF;}
txtadd(t,t2);
NET_send(NETplayer,playerlist[tpl]->net,t);
}
playerlist[tpl]->mobj_last=playerlist[tpl]->mobj;
for (i=0;i<=7;i++){ if ((playerlist[tpl]->party[i]!=NULL)&&((playerlist[tpl]->party[0]!=NULL))){
tnpc=(npc*)playerlist[tpl]->party[i]->more; //shortcut
if (tnpc->upflags){ //upflags (any)
//1 name, portriat, str, dex, int, lev, hp_max, mp_max (all)
//2 hp
//4 mp
//8 xp
//16 weight (automatically set if inventory/equipped items change)
//32 inventory, bag icon
//64 equipped items
//tnpc->upflags=1;
if (tnpc->upflags&1) tnpc->upflags|=(2+4+8+16+32+64);
if (tnpc->upflags&32) tnpc->upflags|=16;
if (tnpc->upflags&64) tnpc->upflags|=16;
if (tnpc->upflags&32){ //reagents changed? spellbook active?
if (tnpc->wep_right){ if (tnpc->wep_right->type==57){
tnpc->upflags|=128;
}}
if (tnpc->wep_left){ if (tnpc->wep_left->type==57){
tnpc->upflags|=128;
}}
}
//WHAT ABOUT WHEN WE TAKE THE SPELLBOOK AWAY!!!!!
//if (tplayer->mobj->type==57){ //ready spellbook
//tnpc->upflags|=128;
//}
//tnpc->wep_right=tplayer->mobj;
if (tnpc->upflags&16){ //recalculate the weight the player is carrying
x=0;
x+=WTfind((object*)tnpc->helm);
x+=WTfind((object*)tnpc->neck);
x+=WTfind((object*)tnpc->wep_left);
x+=WTfind((object*)tnpc->wep_right);
x+=WTfind((object*)tnpc->armour);
x+=WTfind((object*)tnpc->ring_left);
x+=WTfind((object*)tnpc->ring_right);
x+=WTfind((object*)tnpc->boots);
tnpc->wt2=x;
x+=(WTfind((object*)tnpc->items)-20);
tnpc->wt=x;
}
//need an internal loop for each NPC
txtset(t,"????");
txtset(t2,"??");
txtset(t3,"?");
txtset(t4,"????");
txtset(t6,"?");
t->d2[0]=3; //update NPC frame message
t->d2[1]=i; //frame index 0-7
t->ds[1]=tnpc->upflags;
if (tnpc->upflags&32){
//validate inventory position (scroll up as necessary)
revalinv:
x=-1; myobj=(object*)tnpc->baseitem; myobj=(object*)myobj->more;
invval: if (myobj){x++; myobj=(object*)myobj->next; goto invval;}
if (x==-1) x=0;
if (x<tnpc->baseitem_offset){
if (tnpc->baseitem_offset>=4) {tnpc->baseitem_offset-=4;}else{tnpc->baseitem_offset=0;}
goto revalinv;
}
t3->d2[0]=0; txtadd(t,t3); //x2 <--
//x2(64) +display up arrow (only if flag32 set)
//x2(128) +display down arrow (only if flag32 set)
//x2(?) +bag icon (only if flag32 set)
txtsetchar(t5,46);//tnpc non-sellable objects message (currently seperate)
txtaddchar(t5,i);
txtaddshort(t5,0);
y3=0;
//11111 111
//tnpc=tnpc;
//player inventory
myobj=(object*)tnpc->baseitem;
myobj=(object*)myobj->more;
x2=0; //number of items to display
x=61; y=61; x3=tnpc->baseitem_offset;
if (x3) x2+=64; //up arrow
dnib:
if (myobj!=NULL){
if (x3>0) {x3--;goto skipbio1b;}
t2->ds[0]=myobj->type;
if (myobj->info&32768){
t5->ds[1]|=(1<<y3);
}
y3++;
txtadd(t,t2);
//quantity,keys and item + can't exist in same object so changed to else if this should fix oild flask bug also
i6=0;
if (obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].flags&4096){ //items that have quantity
t2->ds[0]=myobj->more2;
txtadd(t,t2);
}
else if ((myobj->type&1023)==64){ //key
t2->ds[0]=myobj->more2;
txtadd(t,t2);
}
else if (obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].v1 || obji[sprlnk[myobj->type&1023]+(myobj->type>>10)].v2){ //v1 (damage), send + info to client
i6=ENHANCEget_attack(myobj);
if (i6==0) {
i6=ENHANCEget_defense(myobj);
}
t6->d2[0]=i6;
txtadd(t,t6);
}
else if ((myobj->type&1023)==448) { //horse papers, send + info to client
myobj2=(object*)myobj->more; crt2=(creature*)myobj2->more;
if (crt2->respawn_x&15){
i6=crt2->respawn_x&15;
}
t6->d2[0]=i6;
txtadd(t,t6);
}
x2++;
x=x+16;
if (x>109) {x=61;y=y+16;}
if (y>109) {
if (myobj->next!=NULL) x2+=128;
goto diskipb;}
if (myobj->next!=NULL){
skipbio1b:
myobj=(object*)myobj->next;
goto dnib;
}
}
diskipb:;
//return (x2&0xF);
if (tnpc->baseitem!=tnpc->items){
t2->ds[0]=tnpc->baseitem->type;
txtadd(t,t2);
x2+=32; //bag item
}
t->d2[4]=x2; //<--x2
NET_send(NETplayer,playerlist[tpl]->net,t5); //send not4sale info
}//tnpc->upflags&32
if (tnpc->upflags&64){ //eqp items update
if (tnpc->helm!=NULL) t2->ds[0]=tnpc->helm->type; else t2->ds[0]=0;
txtadd(t,t2);
if (tnpc->wep_right!=NULL) t2->ds[0]=tnpc->wep_right->type; else t2->ds[0]=0;
txtadd(t,t2);
if (tnpc->wep_left!=NULL) t2->ds[0]=tnpc->wep_left->type; else t2->ds[0]=0;
txtadd(t,t2);
if (tnpc->armour!=NULL) t2->ds[0]=tnpc->armour->type; else t2->ds[0]=0;
txtadd(t,t2);
if (tnpc->boots!=NULL) t2->ds[0]=tnpc->boots->type; else t2->ds[0]=0;
txtadd(t,t2);
if (tnpc->neck!=NULL) t2->ds[0]=tnpc->neck->type; else t2->ds[0]=0;
txtadd(t,t2);
if (tnpc->ring_right!=NULL) t2->ds[0]=tnpc->ring_right->type; else t2->ds[0]=0;
txtadd(t,t2);
if (tnpc->ring_left!=NULL) t2->ds[0]=tnpc->ring_left->type; else t2->ds[0]=0;
txtadd(t,t2);
t2->ds[0]=tnpc->wt2;
txtadd(t,t2);
//as equipment has changed recalculate arm value!
static unsigned short npc_arm;
npc_arm=0;
myobj=tnpc->helm; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
myobj=tnpc->wep_right; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
myobj=tnpc->wep_left; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
myobj=tnpc->armour; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
myobj=tnpc->boots; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
myobj=tnpc->neck; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
myobj=tnpc->ring_right; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
myobj=tnpc->ring_left; if (myobj!=NULL) npc_arm+=obji[sprlnk[myobj->type&1023]].v2+ENHANCEget_defense(myobj);
tnpc->arm=npc_arm;
if (tnpc->protection) tnpc->arm+=10;
if (tnpc->player){ if (tnpc->player->party[0]){ if ((npc*)tnpc->player->party[0]->more==tnpc){ if (tnpc->exp<1600){ if (tnpc->lev<=2){
tnpc->arm+=(20-tnpc->exp/80);
}}}}}
} //tnpc->upflags&64
if (tnpc->upflags&1){
//1 name, portriat, str, dex, int, lev, hp_max, mp_max (does not change often)
t3->d2[0]=tnpc->name->l; txtadd(t,t3);
txtadd(t,tnpc->name);
t2->ds[0]=tnpc->port; txtadd(t,t2);
t2->ds[0]=tnpc->s; txtadd(t,t2);
t2->ds[0]=tnpc->d; txtadd(t,t2);
t2->ds[0]=tnpc->i; txtadd(t,t2);
t2->ds[0]=tnpc->lev; txtadd(t,t2);
t2->ds[0]=tnpc->hp_max; txtadd(t,t2);
t2->ds[0]=tnpc->mp_max; txtadd(t,t2);
t2->ds[0]=tnpc->wt_max; txtadd(t,t2);
t2->ds[0]=tnpc->wt2_max; txtadd(t,t2);
} //tnpc->upflags&1
if (tnpc->upflags&16){ //wt
t2->ds[0]=tnpc->wt; txtadd(t,t2);
} //tnpc->upflags&16
if (tnpc->upflags&2){ //hp
if (tnpc->hp<0) tnpc->hp=0;
if (tnpc->flags&1) t2->ds[0]=(unsigned long)tnpc->hp|32768; else t2->ds[0]=tnpc->hp;
txtadd(t,t2);
} //tnpc->upflags&2
if (tnpc->upflags&4){ //mp
t2->ds[0]=tnpc->mp;
txtadd(t,t2);
} //tnpc->upflags&4
if (tnpc->upflags&8){ //xp
t4->dl[0]=tnpc->exp;
txtadd(t,t4);
} //tnpc->upflags&8
if (tnpc->upflags&128){
ZeroMemory(&tspell,sizeof(tspell));
//enumerate spells
if (myobj=(object*)tnpc->wep_left){ if (myobj->type==57){
myobj=(object*)myobj->more;
nextspell:
if (myobj){
tspell[myobj->more2]=1;
if (myobj->next) {myobj=(object*)myobj->next; goto nextspell;}
}
}}
if (myobj=(object*)tnpc->wep_right){ if (myobj->type==57){
myobj=(object*)myobj->more;
nextspell2:
if (myobj){
//NEW GPF THIS LINE!
tspell[myobj->more2]=1;
if (myobj->next) {myobj=(object*)myobj->next; goto nextspell2;}
}
}}
//enumerate reagents
ZeroMemory(&treagent,sizeof(treagent));
x=OBJlist((object*)tnpc->items->more); //x5=last object number???
OBJlist_last=NULL;
for(x2=0;x2<x;x2++){
x3=OBJlist_list[x2]->type;
if ((x3>=65)&&(x3<=72)){
treagent[x3-65]+=OBJlist_list[x2]->more2;
}
}
//add spell number
//spellreagent[..]
x4=0; //number of spells in spellbook(s)
for (x=0;x<=255;x++){
if (tspell[x]){
x4++;
x3=65536;
for (x2=0;x2<=7;x2++){
if (spellreagent[x]&(1<<x2)){
if (treagent[x2]<x3) x3=treagent[x2];
}//reagent
}//x2
if (x3<65536){ //add spell number
tspell[x]+=x3;
}
}//tspell
}//x spell
//add message
t3->d2[0]=x4; txtadd(t,t3); //numbers of spells
for (x=0;x<=255;x++){
if (tspell[x]){
//txtnumint(t5,x);
//MessageBox(NULL,t5->d,"Ultima 6 Online",MB_OK);
t3->d2[0]=x; txtadd(t,t3);
t2->ds[0]=tspell[x]; txtadd(t,t2);
}
}
}//128
NET_send(NETplayer,playerlist[tpl]->net,t); //send update message
tnpc->upflags=0;
} //upflags
}} //party member loop
} //connection exists
}//current player
}//tpl
if (ouln!=-1){ for (i=0;i<=ouln;i++){ if (oul[i]){
if (oul[i]->info&32768) oul[i]->info-=32768;
}}}
#ifndef _DEBUG
/* this was originally at client loop so I moved it here */
if (ett>=86400){ /*quit every 24h if not debugging*/
for (i=1;i<=playerlist_last;i++){
if (playerlist[i]){ //current player
if (playerlist[i]->net!=INVALID_NET){ //net connection available
goto autoexit_deny;
}}}
u6orevive=255; seek(u6orevive_fh,0); put(u6orevive_fh,&u6orevive,1);
exitrequest=TRUE; exitrequest_noconfirm=TRUE;
}//ett
#endif
autoexit_deny:
revive_infiniteloopexit_i++;
} //NEThost!=NULL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment