bool item::animate(int) { if(!screenIsScrolling()) // Because subscreen items are items, too. :p { if(is_side_view()) { if(can_drop(x,y) && !(pickup & ipDUMMY) && !(pickup & ipCHECK)) { y+=fall/100; if((fall/100)==0 && fall>0) fall*=(fall>0 ? 2 : 0.5); // That oughta do something about the floatiness. if(fall <= (int)zinit.terminalv) { fall += zinit.gravity; } } else if(!can_drop(x,y) && !(pickup & ipDUMMY) && !(pickup & ipCHECK)) { fall = -fall/2; // LA key bounce. } } else { z-=fall/100; if(z<0) { z = 0; fall = -fall/2; } else if(z <= 1 && abs(fall) < (int)zinit.gravity) { z=0; fall=0; } else if(fall <= (int)zinit.terminalv) { fall += zinit.gravity; } } } // Maybe it fell off the bottom in sideview, or was moved by a script. if(y>352 || y<-176 || x<-256 || x > 512) { return true; } if((++clk)>=0x8000) { clk=0x7000; } if(flash) { cs = o_cset; if(frame&8) { cs >>= 4; } else {
void effect_tick(void) { int n,cnt=0,in,m,co,fn,cn,in2,flag,z; for (n=1; n<MAXEFFECT; n++) { if (fx[n].used==USE_EMPTY) continue; cnt++; if (fx[n].used!=USE_ACTIVE) continue; if (fx[n].type==1) { // remove injury flag from map fx[n].duration--; if (fx[n].duration==0) { fx[n].used=USE_EMPTY; map[fx[n].data[0]+fx[n].data[1]*MAPX].flags&=~(MF_GFX_INJURED|MF_GFX_INJURED1|MF_GFX_INJURED2); } } if (fx[n].type==2) { // timer for character respawn if (fx[n].duration) fx[n].duration--; if (fx[n].duration==0 && plr_check_target(fx[n].data[0]+fx[n].data[1]*MAPX)) { m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags|=MF_MOVEBLOCK; fx[n].type=8; } } if (fx[n].type==3) { // death mist fx[n].duration++; if (fx[n].duration==19) { fx[n].used=0; m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_DEATH; } else { m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_DEATH; map[m].flags|=((unsigned long long)fx[n].duration)<<40; if (fx[n].duration==9) { plr_map_remove(fx[n].data[2]); if (can_drop(m)) ; else if (can_drop(m+1)) m+=1; else if (can_drop(m-1)) m+=-1; else if (can_drop(m+MAPX)) m+=MAPX; else if (can_drop(m-MAPX)) m+=-MAPX; else if (can_drop(m+1+MAPX)) m+=1+MAPX; else if (can_drop(m+1-MAPX)) m+=1-MAPX; else if (can_drop(m-1+MAPX)) m+=-1+MAPX; else if (can_drop(m-1-MAPX)) m+=-1-MAPX; else if (can_drop(m+2)) m+=2; else if (can_drop(m-2)) m+=-2; else if (can_drop(m+2*MAPX)) m+=2*MAPX; else if (can_drop(m-2*MAPX)) m+=-2*MAPX; else if (can_drop(m+2+MAPX)) m+=2+MAPX; else if (can_drop(m+2-MAPX)) m+=2-MAPX; else if (can_drop(m-2+MAPX)) m+=-2+MAPX; else if (can_drop(m-2-MAPX)) m+=-2-MAPX; else if (can_drop(m+1+2*MAPX)) m+=1+2*MAPX; else if (can_drop(m+1-2*MAPX)) m+=1-2*MAPX; else if (can_drop(m-1+2*MAPX)) m+=-1+2*MAPX; else if (can_drop(m-1-2*MAPX)) m+=-1-2*MAPX; else if (can_drop(m+2+2*MAPX)) m+=2+2*MAPX; else if (can_drop(m+2-2*MAPX)) m+=2-2*MAPX; else if (can_drop(m-2+2*MAPX)) m+=-2+2*MAPX; else if (can_drop(m-2-2*MAPX)) m+=-2-2*MAPX; else { int temp; co=fx[n].data[2]; temp=ch[co].temp; chlog(co,"could not drop grave"); god_destroy_items(co); ch[co].used=USE_EMPTY; if (ch[co].flags&CF_RESPAWN) fx_add_effect(2,TICKS*60*5+RANDOM(TICKS*60*10),ch_temp[temp].x,ch_temp[temp].y,temp); m=0; } if (m) { co=fx[n].data[2]; flag=0; for (z=0; z<40 && !flag; z++) { if (ch[co].item[z]) { flag=1; break; } } for (z=0; z<20 && !flag; z++) { if (ch[co].worn[z]) { flag=1; break; } } if (ch[co].citem) flag=1; if (ch[co].gold) flag=1; if (flag) { map[m].flags|=MF_MOVEBLOCK; fn=fx_add_effect(4,0,m%MAPX,m/MAPX,fx[n].data[2]); fx[fn].data[3]=fx[n].data[3]; } else { int temp; temp=ch[co].temp; god_destroy_items(co); ch[co].used=USE_EMPTY; if (temp && (ch[co].flags&CF_RESPAWN)) { if (temp==189 || temp==561) { fx_add_effect(2,TICKS*60*20+RANDOM(TICKS*60*5),ch_temp[temp].x,ch_temp[temp].y,temp); } else { fx_add_effect(2,TICKS*60*4+RANDOM(TICKS*60*1),ch_temp[temp].x,ch_temp[temp].y,temp); } xlog("respawn %d (%s): YES",co,ch[co].name); } else xlog("respawn %d (%s): NO",co,ch[co].name); } } } } } if (fx[n].type==4) { // tomb stone fx[n].duration++; if (fx[n].duration==29) { fx[n].used=USE_EMPTY; co=fx[n].data[2]; m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_TOMB; map[m].flags&=~MF_MOVEBLOCK; in=god_create_item(170); it[in].data[0]=co; if (ch[co].data[99]) it[in].max_age[0]*=4; sprintf(it[in].description,"Here rests %s, killed by %s on the %d%s%s%s%s day of the Year %d.", ch[co].reference, fx[n].data[3] ? ch[fx[n].data[3]].reference : "unknown causes", globs->mdday, (globs->mdday==1 ? "st" : ""), (globs->mdday==2 ? "nd" : ""), (globs->mdday==3 ? "rd" : ""), (globs->mdday>3 ? "th" : ""), globs->mdyear); god_drop_item(in,fx[n].data[0],fx[n].data[1]); ch[co].x=it[in].x; ch[co].y=it[in].y; chlog(co,"grave done"); } else { m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_TOMB; map[m].flags|=((unsigned long long)fx[n].duration)<<35; } } if (fx[n].type==5) { // evil magic fx[n].duration++; m=fx[n].data[0]+fx[n].data[1]*MAPX; if (fx[n].duration==8) { fx[n].used=USE_EMPTY; map[m].flags&=~MF_GFX_EMAGIC; } else { map[m].flags&=~MF_GFX_EMAGIC; map[m].flags|=((unsigned long long)fx[n].duration)<<45; } } if (fx[n].type==6) { // good magic fx[n].duration++; m=fx[n].data[0]+fx[n].data[1]*MAPX; if (fx[n].duration==8) { fx[n].used=USE_EMPTY; map[m].flags&=~MF_GFX_GMAGIC; } else { map[m].flags&=~MF_GFX_GMAGIC; map[m].flags|=((unsigned long long)fx[n].duration)<<48; } } if (fx[n].type==7) { // caster magic fx[n].duration++; m=fx[n].data[0]+fx[n].data[1]*MAPX; if (fx[n].duration==8) { fx[n].used=USE_EMPTY; map[m].flags&=~MF_GFX_CMAGIC; } else { map[m].flags&=~MF_GFX_CMAGIC; map[m].flags|=((unsigned long long)fx[n].duration)<<51; } } if (fx[n].type==8) { // repawn mist fx[n].duration++; if (fx[n].duration==19) { fx[n].used=0; m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_DEATH; } else { m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_DEATH; map[m].flags|=((unsigned long long)fx[n].duration)<<40; if (fx[n].duration==9) { m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_MOVEBLOCK; if (!pop_create_char(fx[n].data[2],1) && (ch_temp[fx[n].data[2]].flags&CF_RESPAWN)) { fx[n].type=2; fx[n].duration=TICKS*60*5; // try again every 5 minutes map[m].flags&=~MF_GFX_DEATH; } } } } if (fx[n].type==9) { // controlled item animation with optional monster creation fx[n].duration--; in=fx[n].data[0]; if (!(fx[n].duration&1)) it[in].status[1]++; if (fx[n].duration==0) { map[it[in].x+it[in].y*MAPX].it=0; if (fx[n].data[1]) { cn=pop_create_char(fx[n].data[1],0); god_drop_char(cn,it[in].x,it[in].y); ch[cn].dir=DX_RIGHTUP; plr_reset_status(cn); } fx[n].used=USE_EMPTY; it[in].used=USE_EMPTY; } } if (fx[n].type==10) { // respawn object if (fx[n].duration) fx[n].duration--; else { m=fx[n].data[0]+fx[n].data[1]*MAPX; // check if object isnt allowed to respawn (supporting beams for mine) if (is_beam(map[m].it) || is_beam(map[m-1].it) || is_beam(map[m+1].it) || is_beam(map[m-MAPX].it) || is_beam(map[m+MAPX].it) || is_beam(map[m-2].it) || is_beam(map[m+2].it) || is_beam(map[m-2*MAPX].it) || is_beam(map[m+2*MAPX].it) || is_beam(map[m-1+1*MAPX].it) || is_beam(map[m+1+1*MAPX].it) || is_beam(map[m-1-1*MAPX].it) || is_beam(map[m+1-1*MAPX].it) || is_beam(map[m-2+1*MAPX].it) || is_beam(map[m+2+1*MAPX].it) || is_beam(map[m-2-1*MAPX].it) || is_beam(map[m+2-1*MAPX].it) || is_beam(map[m-1+2*MAPX].it) || is_beam(map[m+1+2*MAPX].it) || is_beam(map[m-1-2*MAPX].it) || is_beam(map[m+1-2*MAPX].it) || is_beam(map[m-2+2*MAPX].it) || is_beam(map[m+2+2*MAPX].it) || is_beam(map[m-2-2*MAPX].it) || is_beam(map[m+2-2*MAPX].it)) { fx[n].duration=TICKS*60*15; continue; } in2=map[m].it; map[m].it=0; in=god_create_item(fx[n].data[2]); if (!god_drop_item(in,fx[n].data[0],fx[n].data[1])) { fx[n].duration=TICKS*60; it[in].used=USE_EMPTY; map[m].it=in2; } else { fx[n].used=USE_EMPTY; if (in2) it[in2].used=USE_EMPTY; reset_go(fx[n].data[0],fx[n].data[1]); } } } if (fx[n].type==11) { // remove queued spell flags fx[n].duration--; if (fx[n].duration<1) { fx[n].used=USE_EMPTY; ch[fx[n].data[0]].data[96]&=~fx[n].data[1]; } } if (fx[n].type==12) { // death mist fx[n].duration++; if (fx[n].duration==19) { fx[n].used=0; m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_DEATH; } else { m=fx[n].data[0]+fx[n].data[1]*MAPX; map[m].flags&=~MF_GFX_DEATH; map[m].flags|=((unsigned long long)fx[n].duration)<<40; } } } globs->effect_cnt=cnt; }
/** Update the current poses of the robot */ static void conscious_thought(void) { char *scmd; int execute; struct timeval currtime; // get a speech command, and place that as // the priority task /*if ((scmd = get_speech_command())) { if (strstr(scmd, "fetch")) { task = "fetch"; } else if (strstr(scmd, "stop")) { task = "stop"; } }*/ // FSM (taskgraph) execute = 0; printf("Updating objects...\n"); update_object_positions(); gettimeofday(&currtime, NULL); printf("Object positions:\n"); printf("<ball>\n"); for (int n = 0; n < (int)ballpos.size(); n++) { printf("Ball: %f %f %f\n", ballpos[n].x, ballpos[n].y, ballpos[n].z); } printf("</ball>\n"); printf("<basket>\n"); for (int n = 0; n < (int)basketpos.size(); n++) { printf("Basket: %f %f %f\n", basketpos[n].x, basketpos[n].y, basketpos[n].z); } printf("</basket>\n"); printf("Updating states...\n"); while (!execute) { if (strcmp(task, "fetch") == 0) { // transitions // TODO: create a counter resolution for infinite loops // TODO: pick up more than 1 ball switch (subtask) { case S_IDLE: printf("State: IDLE\n"); if (num_balls_in_basket() == 0) { subtask = S_FINDBALL; } else { subtask = S_FINDBASKET; // execute = 1; } break; case S_FINDBALL: printf("State: FIND BALL\n"); if (num_balls_in_basket() != 0) { subtask = S_IDLE; } else if (!ballfound()) { execute = 1; } else { subtask = S_GOTOBALL; } break; case S_GOTOBALL: printf("State: GOTO BALL\n"); if (num_balls_in_basket() != 0) { subtask = S_IDLE; } else if (!ballfound()) { subtask = S_FINDBALL; } else if (can_pickup(closest_object(ballpos))) { subtask = S_PICKBALL; } else { execute = 1; } break; case S_PICKBALL: printf("State: PICK BALL\n"); if (num_balls_in_basket() != 0) { subtask = S_IDLE; } else if (!ballfound()) { subtask = S_FINDBALL; } else if (!can_pickup(closest_object(ballpos))) { subtask = S_GOTOBALL; } else { execute = 1; } break; case S_FINDBASKET: printf("State: FIND BASKET\n"); if (!basketfound()) { execute = 1; } else { subtask = S_GOTOBASKET; } break; case S_GOTOBASKET: printf("State: GOTO BASKET\n"); if (!basketfound()) { subtask = S_FINDBASKET; } else if (can_drop(closest_object(basketpos))) { // have to do a strange thing here with timers gettimeofday(&actiontime, NULL); subtask = S_DROPBASKET_PHASE1; } else { execute = 1; } break; case S_DROPBASKET_PHASE1: printf("State: DROP BASKET P1\n"); if (difftime(currtime, actiontime) < 1.2) { execute = 1; } else { gettimeofday(&actiontime, NULL); subtask = S_DROPBASKET_PHASE2; } break; case S_DROPBASKET_PHASE2: printf("State: DROP BASKET P2\n"); if (difftime(currtime, actiontime) < 0.5) { execute = 1; } else { gettimeofday(&actiontime, NULL); subtask = S_DROPBASKET_PHASE3; } break; case S_DROPBASKET_PHASE3: printf("State: DROP BASKET P3\n"); if (difftime(currtime, actiontime) < 1.0) { execute = 1; } else { gettimeofday(&actiontime, NULL); subtask = S_DROPBASKET_PHASE4; } break; case S_DROPBASKET_PHASE4: printf("State: DROP BASKET P4\n"); if (difftime(currtime, actiontime) < 1.0) { execute = 1; } else { gettimeofday(&actiontime, NULL); subtask = S_DROPBASKET_PHASE5; } break; case S_DROPBASKET_PHASE5: printf("State: DROP BASKET P5\n"); if (difftime(currtime, actiontime) < 1.2) { execute = 1; } else { subtask = S_IDLE; } break; default: subtask = S_IDLE; } } else if (strcmp(task, "stop") == 0) { subtask = S_IDLE; printf("State: IDLE\n"); execute = 1; } } printf("Executing...\n"); // move accordingly to the state // TODO: do collision detection, stop the robot from moving switch (subtask) { case S_IDLE: set_robot(0.0, 0.0, 0.0, 0.0); break; case S_FINDBALL: set_robot(0.0, 0.30 * find_coeff, 0.0, 0.0); break; case S_GOTOBALL: set_robot(0.32, -ballpos[0].x / 1000.0, -1.0, 0.0); find_coeff = dsign(-ballpos[0].x); break; case S_PICKBALL: set_robot(0.30, -ballpos[0].x / 1000.0, -1.0, 1.0); find_coeff = dsign(-ballpos[0].x); break; case S_FINDBASKET: set_robot(0.0, -0.30 * find_coeff, 0.0, 0.0); break; case S_GOTOBASKET: set_robot(0.32, -basketpos[0].x / 1200.0, 0.0, 0.0); find_coeff = dsign(-basketpos[0].x); break; case S_DROPBASKET_PHASE1: set_robot(0.0, 0.0, 1.0, 0.0); break; case S_DROPBASKET_PHASE2: set_robot(0.40, -basketpos[0].x / 1200.0, 0.0, 0.0); find_coeff = dsign(-basketpos[0].x); break; case S_DROPBASKET_PHASE3: set_robot(0.0, 0.0, 0.0, -1.0); break; case S_DROPBASKET_PHASE4: set_robot(-0.40, 0.0, 0.0, 0.0); break; case S_DROPBASKET_PHASE5: set_robot(0.0, 0.0, -1.0, 0.0); break; default: set_robot(0.0, 0.0, 0.0, 0.0); } }