void Nokia1202::_flush() { uint16_t i, j; for(i=0; i < NOKIA1202_LINES; i++) { if (_dirtybits[i]) { if (_dirtybits[i] == 0xFFFF) { setxy(0, i); digitalWrite(_csPin, LOW); for (j=0; j < NOKIA1202_COLUMNS; j++) { bulkwrite(font_5x7[_framebuffer[i * NOKIA1202_COLUMNS + j]-' '], NOKIA1202_CHAR_WIDTH); } digitalWrite(_csPin, HIGH); } else { for (j=0; j < NOKIA1202_COLUMNS; j++) { if (_dirtybits[i] & 1 << j) { setxy(j * NOKIA1202_CHAR_WIDTH, i); _writefont(_framebuffer[i * NOKIA1202_COLUMNS + j]); _dirtybits[i] &= ~(1 << j); } } } } } }
/* Fully erase DDRAM */ void Nokia1202::clear() { int i; setxy(0, 0); digitalWrite(_csPin, LOW); for (i=0; i < NOKIA1202_COLUMNS * NOKIA1202_CHAR_WIDTH * (NOKIA1202_LINES+1); i++) { SPI.transfer9( 0x100 ); // Write 0 } digitalWrite(_csPin, HIGH); _x = 0; _y = 0; setxy(0, 0); #ifdef NOKIA1202_USE_FRAMEBUFFER // Clear framebuffer RAM for (i=0; i < NOKIA1202_COLUMNS * NOKIA1202_LINES; i++) _framebuffer[i] = ' '; // Clear dirtybits array for (i=0; i < NOKIA1202_LINES; i++) _dirtybits[i] = 0x0000; #endif // Plant the cursor at its new position. if (_useCursor) { #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[0] = 0x80; #endif _writefont(0x80); setxy(0, 0); } }
/* A .setCursor() UI function so the user can move the cursor around. * It has to manage the erasing/rewriting of the cursor too, if applicable. */ void Nokia1202::setCursor(uint8_t x, uint8_t y) { if (x >= NOKIA1202_COLUMNS || y >= NOKIA1202_LINES) return; // Erase the cursor presently at _x,_y before moving it if (_useCursor) { #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' '; _dirtybits[_y] |= 1 << _x; #else _writefont(' '); #endif } _x = x; _y = y; if (_useCursor) { #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = 0x80; _dirtybits[_y] |= 1 << _x; _flush(); #else setxy(_x * NOKIA1202_CHAR_WIDTH, _y); _writefont(0x80); #endif } // Note the ifNdef here: #ifndef NOKIA1202_USE_FRAMEBUFFER setxy(_x * NOKIA1202_CHAR_WIDTH, _y); #endif }
void tty_erase_screen (void) { #ifdef _WIN32 CONSOLE_SCREEN_BUFFER_INFO info; if (!GetConsoleScreenBufferInfo (tty_stdout, &info)) { printf ("tty_erase_screen: can't get Console buffer info!\r\n"); return; } if (info.srWindow.Top + 25 > info.dwSize.Y) tty_start_y = info.dwSize.Y - 25; else tty_start_y = info.srWindow.Top; tty_start_x = 0; tty_max_x = 79; tty_max_y = info.srWindow.Bottom; #if 0 printf ("Cursor: X=%u, Y=%u\r\n", info.dwCursorPosition.X, info.dwCursorPosition.Y); printf ("Max. window size: Width=%u, Height=%u\r\n", info.dwMaximumWindowSize.X, info.dwMaximumWindowSize.Y); printf ("Size: Width=%u, Height=%u\r\n", info.dwSize.X, info.dwSize.Y); printf ("Window: Bottom=%u, Left=%u, Right=%u, Top=%u\r\n", info.srWindow.Bottom, info.srWindow.Left, info.srWindow.Right, info.srWindow.Top); printf ("Attributes: 0x%04x\r\n", info.wAttributes); #endif setregion (tty_start_x, tty_start_y, ' ', tty_attribs, tty_max_x - tty_start_x + 1, tty_max_y - tty_start_y + 1); setxy (tty_start_x, tty_start_y); #else printf ("\x1b[2J"); tty_gotoxy (1, 1); fflush (stdout); #endif }
void home_task(void) { task_open(); current_menu_item = 1; current_tid = 0; while(1) { if( current_tid == 0) { clearBuff(); setxy(2,4); xprint("%s\n0x%04X",mainMenu[current_menu_item].name,mainMenu[current_menu_item].task ); lcd_xmit(); } event_wait( buttonEvent ); char button_state = button_get_pressed(); if(current_tid == 0) { if(( button_state & BUTTON_DOWN )&&( current_menu_item > 0 )) { current_menu_item--; // antmation? } else if(( button_state & BUTTON_UP )&&( current_menu_item < N_MENU -1 )) { current_menu_item++; } else if(( button_state & BUTTON_SELECT )) // no task running { // call up a new task task_create( mainMenu[current_menu_item].task, 10, 0, 0, 0 ); // should be a lower priority than this task // store tid current_tid = 1;//task_id_get( mainMenu[current_menu_item].task ); } } else { if(( button_state & BUTTON_MENU )) { task_kill( mainMenu[current_menu_item].task ); current_tid = 0; } } task_wait(10); //P2OUT ^= BIT3; } task_close(); }
void BOX::xyout(int x, int y, const string &s, COLORS b, COLORS bc) const { textcolor(b); textbackground(bc); cout << setxy(left+1+x, top+y) << s; textcolor(color); textbackground(bgcolor); }
void tty_restore_cursor (void) { #ifdef _WIN32 setxy (tty_saved_x, tty_saved_y); #else printf ("\x1b[u"); fflush (stdout); #endif }
void BOX::textbox(const string &msg) const { textcolor(color); textbackground(bgcolor); highvideo(); draw_box(); cout << setxy(left+2, top+1) << msg; normvideo(); }
void BOX::draw_box() const { cout << setxy(left, top) << "¢z"; cout << setxy(left+width-2, top) << "¢{"; cout << setxy(left, top+height-1) << "¢|"; cout << setxy(left+width-2, top+height-1) << "¢}"; for(int x=left+2; x<left+width-2; x+=2) { cout << setxy(x, top) << "¢w"; cout << setxy(x, top+height-1) << "¢w"; } for(int y=top+1; y<top+height-1; ++y) { cout << setxy(left, y) << "¢x" << string(width-4, ' ') << "¢x"; } cout << setxy(left+4, top) << title; cout << setxy(left+width-2-footer.size(), top+height-1) << footer; }
STDMETHODIMP CPDObjectSymbolInstance::Move(/*[in]*/ double dx, /*[in]*/ double dy) { setxy(m_x+dx, m_y+dy); return S_OK; }
void SWSerLCDpa::setxy(int x, int y, int n) { setxy(x,y); print(n); }
void SWSerLCDpa::setxy(int x, int y, long n, int base) { setxy(x,y); print(n, base); }
void SWSerLCDpa::setxy(int x, int y, const char *s) { setxy(x,y); print(s); }
void SWSerLCDpa::clearline(int line) { setxy(0,line); print("?l"); delay(20); }
// death is called when an object dies (weapon destructed, etc.) // for special effects .. short weap::death() { // Note that the 'dead' variable should ALREADY be set by the // time this function is called, so that we can easily reverse // the decision :) walker *newob = NULL; if (death_called) // Make sure we don't get multiple deaths return 0; death_called = 1; switch (family) { case FAMILY_KNIFE: // for returning knife if (owner && owner->query_family() != FAMILY_SOLDIER) break; // only soldiers get returning knives newob = screenp->add_ob(ORDER_FX, FAMILY_KNIFE_BACK); newob->owner = owner; newob->center_on(this); newob->lastx = lastx; newob->lasty = lasty; newob->stepsize = stepsize; newob->ani_type = ANI_ATTACK; newob->damage = damage; break; // end of soldier returning knife case FAMILY_ROCK: // used for the elf's bouncing rock, etc. if (!do_bounce || !lineofsight || collide_ob) // died of natural causes break; dead = 0; // first, un-dead us so we can collide .. // Did we hit a barrier? if (screenp->query_grid_passable(xpos+lastx, ypos+lasty, this)) { dead = 1; break; // if not, die like normal } if (screenp->query_grid_passable(xpos-lastx, ypos+lasty, this)) { setxy(xpos-lastx, ypos+lasty); // bounce 'down-left' lastx = -lastx; death_called = 0; break; } if (screenp->query_grid_passable(xpos+lastx, ypos-lasty, this)) { setxy(xpos+lastx, ypos-lasty); // bounce 'up-right' lasty = -lasty; death_called = 0; break; } if (screenp->query_grid_passable(xpos-lastx, ypos-lasty, this)) { setxy(xpos-lastx, ypos-lasty); lastx = -lastx; lasty = -lasty; death_called = 0; break; } // Else we're really stuck, so die :) dead = 1; break; case FAMILY_FIRE_ARROW: // only for exploding, really case FAMILY_BOULDER: if (!skip_exit) break; // skip_exit means we're supposed to explode :) if (!owner || owner->dead) owner = this; newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION, 1); if (!newob) break; // failsafe if (on_screen()) screenp->soundp->play_sound(SOUND_EXPLODE); newob->owner = owner; newob->stats->hitpoints = 0; newob->stats->level = owner->stats->level; newob->ani_type = ANI_EXPLODE; newob->center_on(this); newob->damage = damage*2; break; // end fire (exploding) arrows case FAMILY_WAVE: // grow to wave2 dead = 0; transform_to(ORDER_WEAPON, FAMILY_WAVE2); stats->hitpoints = stats->max_hitpoints; break; // end wave -> wave2 case FAMILY_WAVE2: // grow to wave3 dead = 0; transform_to(ORDER_WEAPON, FAMILY_WAVE3); stats->hitpoints = stats->max_hitpoints; break; // end wave2 -> wave3 case FAMILY_DOOR: // display open picture newob = screenp->add_weap_ob(ORDER_FX, FAMILY_DOOR_OPEN); if (!newob) break; newob->ani_type = ANI_DOOR_OPEN; newob->setxy(xpos, ypos); newob->stats->level = stats->level; newob->team_num = team_num; // newob->ignore = 1; // What way are we 'facing'? if (mysmoother->query_genre_x_y((xpos/GRID_SIZE),(ypos/GRID_SIZE)-1) == TYPE_WALL) // a wall above us? { newob->curdir = FACE_RIGHT; // newob->setxy(xpos, ypos-12); // and move us 'up' } else { curdir = FACE_UP; } break; // end open the door .. default: break; } return 1; }
// Intelligent writing & processing of a single character size_t Nokia1202::write(uint8_t c) { uint8_t i = 0; // Process the character as-is if (c > 0x82) c = 0x20; if (c >= 0x20) { #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = c; _dirtybits[_y] |= 1 << _x; #else _writefont(c); #endif _x++; } else { // Process control character switch (c) { case '\n': if (_useCursor) { // Erase the cursor presently at _x,_y before moving it #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' '; _dirtybits[_y] |= 1 << _x; #else _writefont(' '); #endif } _x = 0; _y++; // Note the "ifNdef" in this line: #ifndef NOKIA1202_USE_FRAMEBUFFER setxy(_x * NOKIA1202_CHAR_WIDTH, _y); #endif break; case '\t': if (_useCursor) { // Erase the cursor presently at _x,_y before moving it #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' '; _dirtybits[_y] |= 1 << _x; #else _writefont(' '); #endif } if (_x % _tabSpacing == 0) { _x += _tabSpacing; } else { _x += _x % _tabSpacing; } #ifndef NOKIA1202_USE_FRAMEBUFFER setxy(_x * NOKIA1202_CHAR_WIDTH, _y); #endif break; case '\b': if (_useCursor) { // Erase the cursor presently at _x,_y before moving it #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' '; _dirtybits[_y] |= 1 << _x; #else _writefont(' '); #endif } if (_x > 0) { _x--; #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = ' '; _dirtybits[_y] |= 1 << _x; #else setxy(_x * NOKIA1202_CHAR_WIDTH, _y); _writefont(' '); setxy(_x * NOKIA1202_CHAR_WIDTH, _y); #endif } break; // No default section; any other ctrl char is ignored } } if (_x >= NOKIA1202_COLUMNS) { // Shift down 1 row _y++; _x = 0; } if (_y >= NOKIA1202_LINES) { // Ut oh, we must scroll (or roll back to the top in no-framebuffer mode) #ifdef NOKIA1202_USE_FRAMEBUFFER for (i=1; i < NOKIA1202_LINES; i++) { // Copy line to line above memcpy(_framebuffer + (i-1) * NOKIA1202_COLUMNS, _framebuffer + i * NOKIA1202_COLUMNS, NOKIA1202_COLUMNS); _dirtybits[i-1] = 0xFFFF; } // Cursor re-set to the bottom line _y = NOKIA1202_LINES - 1; // Clear the bottom line memset(_framebuffer + _y * NOKIA1202_COLUMNS, ' ', NOKIA1202_COLUMNS); _dirtybits[_y] = 0xFFFF; #else _y = 0; #endif } // Plant the cursor at its new position. if (_useCursor) { #ifdef NOKIA1202_USE_FRAMEBUFFER _framebuffer[_y * NOKIA1202_COLUMNS + _x] = 0x80; _dirtybits[_y] |= 1 << _x; #else setxy(_x * NOKIA1202_CHAR_WIDTH, _y); _writefont(0x80); #endif } // Commit data to screen (framebuffer mode) or set cursor position (non-framebuffer mode) #ifdef NOKIA1202_USE_FRAMEBUFFER if (_doFlush) // An optimization that makes puts() a lot faster... _flush(); #else setxy(_x * NOKIA1202_CHAR_WIDTH, _y); #endif return 1; }
short effect::act() { short temp; Sint32 xd, yd, distance, generic; oblink *foelist, *here; walker *newob; short numfoes; // Make sure everyone we're poshorting to is valid if (foe && foe->dead) foe = NULL; if (leader && leader->dead) leader = NULL; if (owner && owner->dead) owner = NULL; collide_ob = NULL; // always start with no collison.. // Any special actions .. switch (family) // determine what to do.. { case FAMILY_GHOST_SCARE: if (owner) center_on(owner); break; case FAMILY_MAGIC_SHIELD: // revolve around owner if (!owner || owner->dead) { dead = 1; death(); break; } switch (drawcycle % 16) { case 0: xd = 0; yd = -24; break; case 1: xd = -9; yd = -22; break; case 2: xd = -17; yd = -17; break; case 3: xd = -22; yd = -9; break; case 4: xd = -24; yd = 0; break; case 5: xd = -22; yd = 9; break; case 6: xd = -17; yd = 17; break; case 7: xd = -9; yd = 22; break; case 8: xd = 0; yd = 24; break; case 9: xd = 9; yd = 22; break; case 10: xd = 17; yd = 17; break; case 11: xd = 22; yd = 9; break; case 12: xd = 24; yd = 0; break; case 13: xd = 22; yd = -9; break; case 14: xd = 17; yd = -17; break; case 15: xd = 9; yd = -22; break; } center_on(owner); setxy( (short)( xpos+xd ), (short) (ypos+yd) ); foelist = screenp->find_foe_weapons_in_range( screenp->oblist, sizex, &temp, this); here = foelist; while (foelist) // first weapons { stats->hitpoints -= foelist->ob->damage; foelist->ob->dead = 1; foelist->ob->death(); foelist = foelist->next; } delete_list(here); foelist = screenp->find_foes_in_range( screenp->oblist, sizex, &temp, this); here = foelist; while (foelist) // second enemies { stats->hitpoints -= foelist->ob->damage; attack(foelist->ob); dead = 0; foelist = foelist->next; } delete_list(here); if ( (stats->hitpoints <= 0) || (lifetime-- < 0) ) { dead = 1; death(); } break; // end of magic shield case case FAMILY_BOOMERANG: // fighter's boomerang // Zardus: FIX: if the drawcycle is in its >253s, the boomerang dies. This will fix the bug where // the boomerang comes back to 0 (owner) after spiraling around all the way if the owner has // that good of an ability (to keep its life so high). This caps boomerang ability, though... Another // fix could be to make the drawcycle var an int or at least something with more capacity than char. if (!owner || owner->dead || drawcycle > 253) { dead = 1; death(); break; } switch (drawcycle % 16) { case 0: xd = 0; yd = -24; break; case 1: xd = -9; yd = -22; break; case 2: xd = -17; yd = -17; break; case 3: xd = -22; yd = -9; break; case 4: xd = -24; yd = 0; break; case 5: xd = -22; yd = 9; break; case 6: xd = -17; yd = 17; break; case 7: xd = -9; yd = 22; break; case 8: xd = 0; yd = 24; break; case 9: xd = 9; yd = 22; break; case 10: xd = 17; yd = 17; break; case 11: xd = 22; yd = 9; break; case 12: xd = 24; yd = 0; break; case 13: xd = 22; yd = -9; break; case 14: xd = 17; yd = -17; break; case 15: xd = 9; yd = -22; break; } xd *= (drawcycle+4); xd /= 48; yd *= (drawcycle+4); yd /= 48; center_on(owner); setxy((short) (xpos+xd), (short) (ypos+yd) ); foelist = screenp->find_foe_weapons_in_range( screenp->oblist, sizex*2, &temp, this); here = foelist; while (foelist) // first weapons { stats->hitpoints -= foelist->ob->damage; foelist->ob->dead = 1; foelist->ob->death(); foelist = foelist->next; } delete_list(here); foelist = screenp->find_foes_in_range( screenp->oblist, sizex, &temp, this); here = foelist; while (foelist) // second enemies { stats->hitpoints -= foelist->ob->damage; attack(foelist->ob); dead = 0; foelist = foelist->next; } delete_list(here); if ( (stats->hitpoints <= 0) || (lifetime-- < 0) ) { dead = 1; death(); } break; // end of boomerang case case FAMILY_KNIFE_BACK: // returning blade if (!owner || owner->dead) { dead = 1; break; } distance = distance_to_ob(owner); if (distance > 10) { xd = yd = 0; // zero out distance movements if (owner->xpos > xpos) { if ( (owner->xpos - xpos) > stepsize ) xd = stepsize; else xd = owner->xpos - xpos; } else if (owner->xpos < xpos) { if ( (xpos - owner->xpos) > stepsize ) xd = -stepsize; else xd = owner->xpos - xpos; } if (owner->ypos > ypos) { if ( (owner->ypos - ypos) > stepsize ) yd = stepsize; else yd = owner->ypos - ypos; } else if (owner->ypos < ypos) { if ( (ypos - owner->ypos) > stepsize ) yd = -stepsize; else yd = owner->ypos - ypos; } setxy((short) (xpos+xd), (short) (ypos+yd) ); newob = screenp->add_ob(ORDER_WEAPON, FAMILY_KNIFE); newob->damage = damage; newob->owner = owner; newob->team_num = team_num; newob->death_called = 1; // to ensure no spawning of more .. newob->setxy(xpos, ypos); if (!screenp->query_object_passable((short) (xpos+xd), (short) (ypos+yd), newob)) { newob->attack(newob->collide_ob); damage /= 4; //setxy(xpos-(2*xd)+random(xd), ypos-(2*yd)+random(yd)); } newob->dead = 1; } else { owner->weapons_left++; //if (owner->user != -1) //{ // sprintf(message, "Knives now %d", owner->weapons_left); // screenp->do_notify(message, owner); //} ani_type = ANI_WALK; dead = 1; } break; case FAMILY_CLOUD: // poison cloud if (lifetime > 0) lifetime--; else { dead = 1; death(); } if (lifetime < 8) invisibility_left +=3; if (invisibility_left > 0) invisibility_left--; // Hit any nearby foes (not friends, for now) foelist = screenp->find_foes_in_range( screenp->oblist, sizex, &temp, this); here = foelist; while (foelist) // { if (hits(xpos, ypos, sizex, sizey, // this is the cloud foelist->ob->xpos, foelist->ob->ypos, foelist->ob->sizex, foelist->ob->sizey) ) { attack(foelist->ob); } // end of actual hit foelist = foelist->next; } delete_list(here); // Are we performing some action? if (stats->commandlist) temp = stats->do_command(); else { xd = yd = 0; while (xd == 0 && yd == 0) { xd = random(3)-1; yd = random(3)-1; } stats->add_command(COMMAND_WALK, (short) random(20), (short) xd, (short) yd); } break; // end of cloud case FAMILY_CHAIN: // chain lightning .. if (!leader || lineofsight<1 || !owner) // lost our leader, etc.? kill us .. { dead = 1; death(); return 1; } // Are we at our leader? If so, attack him :) if (hits(xpos, ypos, sizex, sizey, leader->xpos, leader->ypos, leader->sizex, leader->sizey)) { // Do things .. newob = screenp->add_ob(ORDER_FX, FAMILY_EXPLOSION); if (!newob) { dead = 1; death(); return 1; // failsafe } newob->owner = owner; newob->team_num = team_num; newob->stats->level = stats->level; newob->damage = damage; newob->ani_type = ANI_EXPLODE; newob->center_on(this); leader->skip_exit += 3; // can't hit us for 3 rounds .. if (on_screen()) screenp->soundp->play_sound(SOUND_EXPLODE); // Now make new objects to seek out foes .. // First, are our offspring powerful enough at 1/2 our power? generic = (damage)/2; if (owner->myguy) foelist = screenp->find_foes_in_range(screenp->oblist, 240+(owner->myguy->intelligence/2), &temp, this); else foelist = screenp->find_foes_in_range(screenp->oblist, 240+stats->level*5, &temp, this); if (temp && generic>20) // more foes to find .. { here = foelist; numfoes = random(owner->stats->level)+1; while (here && numfoes--) { if (here->ob != leader && here->ob->skip_exit<1) // don't hit current guy, etc. { newob = screenp->add_ob(ORDER_FX, FAMILY_CHAIN); if (!newob) { delete_list(foelist); return 0; // failsafe } newob->owner = owner; // our caster newob->leader = here->ob; // guy to attack newob->stats->level = stats->level; newob->stats->set_bit_flags(BIT_MAGICAL, 1); newob->damage = generic; newob->team_num = team_num; newob->center_on(this); } // end of wasn't current guy case here = here->next; } // end of loop for nearby foes we found } // end of check for nearby foes // Clean up our list .. ? // Zardus: TAG: nah, lets use delete_list /*here = foelist->next; while (here) { delete foelist; foelist = here; here = here->next; } delete foelist;*/ delete_list(foelist); dead = 1; death(); return 1; } // Move toward our leader .. lineofsight--; distance = distance_to_ob_center(leader); if (distance > stepsize*2) { xd = yd = 0; // zero out distance movements if (leader->xpos > xpos) { if ( (leader->xpos - xpos) > stepsize ) xd = stepsize; else xd = leader->xpos - xpos; } else if (leader->xpos < xpos) { if ( (xpos - leader->xpos) > stepsize ) xd = -stepsize; else xd = leader->xpos - xpos; } if (leader->ypos > ypos) { if ( (leader->ypos - ypos) > stepsize ) yd = stepsize; else yd = leader->ypos - ypos; } else if (leader->ypos < ypos) { if ( (ypos - leader->ypos) > stepsize ) yd = -stepsize; else yd = leader->ypos - ypos; } // Set our facing? curdir = facing(xd, yd); set_frame(ani[curdir][0]); } // end of big step else { //xd = leader->xpos; //yd = leader->ypos; center_on(leader); return 1; } setxy((short) (xpos+xd), (short) (ypos+yd) ); return 1; // so as not to animate, etc. //break; // end of FAMILY_CHAIN case FAMILY_DOOR_OPEN: // Here is how doors work. They start out as a FAMILY_DOOR // from ORDER_WEAPON under the weaplist. When the door is // collided with, the obmap marks the door as dead, and spawns // the FAMILY_DOOR_OPEN on the weaplist (this object). It // animates ANI_DOOR_OPEN, and when it is done, it dies and // spawns a FAMILY_DOOR_OPEN on the fxlist. The amusing part // is that now that it is on the fxlist, it won't act anymore, // thus preventing it from continuously respawning itself. if (ani_type != ANI_WALK) return animate(); newob = screenp->add_fx_ob(ORDER_FX, FAMILY_DOOR_OPEN); if (!newob) break; newob->ani_type = ANI_WALK; newob->setxy(xpos, ypos); newob->stats->level = stats->level; newob->team_num = team_num; newob->ignore = 1; newob->curdir = curdir; // set correct frame newob->animate(); dead = 1; death(); return 1; break; default: break; } // Complete previous animations (like firing) if (ani_type != ANI_WALK) return animate(); switch (family) // determine what to do.. { default: dead = 1; death(); break; } return 0; }