/* * InterfaceUserChanged: Player object changed; update safety flag and redraw player. */ void InterfaceUserChanged(void) { room_contents_node *r; Bool new_safety; UserAreaRedraw(); AliasInit(); r = GetRoomObjectById(cinfo->player->id); if (r == NULL) return; new_safety = ((r->obj.flags & OF_SAFETY) != 0); if (new_safety) { if (cinfo->config->aggressive) { if (!safety_flipped) SendSafety(0); safety_flipped = True; } else { pinfo.aggressive = cinfo->config->aggressive = False; safety_flipped = False; } } else { if (!cinfo->config->aggressive) { if (!safety_flipped) SendSafety(1); safety_flipped = True; } else { pinfo.aggressive = cinfo->config->aggressive = True; safety_flipped = False; } } }
/* * ProjectileAdd: Start a new projectile on its way. Projectile goes * from source object to destination object (both objects must be in the room). */ void ProjectileAdd(Projectile *p, ID source_obj, ID dest_obj, BYTE speed, WORD flags, WORD reserved) { float distance; int dx, dy, dz; room_contents_node *s, *d; // If animation off, don't bother with projectiles if (!config.animate) return; debug(("Adding new projectile\n")); // Set source and destination coordinates based on object locations s = GetRoomObjectById(source_obj); d = GetRoomObjectById(dest_obj); if (s == NULL || d == NULL) { debug(("Projectile add got object not in room\n")); return; } if (s == d) { debug(("Projectile add got source == dest\n")); return; } p->motion.source_x = s->motion.x; p->motion.source_y = s->motion.y; p->motion.source_z = s->motion.z; //GetPointFloor(s->motion.x, s->motion.y); #if 0 if (source_obj == player.id) p->motion.source_z += PlayerGetHeightOffset() / (FINENESS * 2); else p->motion.source_z += s->obj.boundingHeight / (FINENESS * 2); #endif p->motion.dest_x = d->motion.x; p->motion.dest_y = d->motion.y; p->motion.dest_z = d->motion.z; //GetPointFloor(d->motion.x, d->motion.y); #if 0 if (dest_obj == player.id) p->motion.dest_z += PlayerGetHeightOffset() / (FINENESS * 2); else p->motion.dest_z += d->obj.boundingHeight / (FINENESS * 2); #endif // debug(("source obj = %d, x = %d, y = %d, z = %d\n", source_obj, // p->motion.source_x, p->motion.source_y, p->motion.source_z)); // // debug(("dest obj = %d, x = %d, y = %d, z = %d\n", dest_obj, // p->motion.dest_x, p->motion.dest_y, p->motion.dest_z)); // See how far we should move per frame dx = p->motion.dest_x - p->motion.source_x; dy = p->motion.dest_y - p->motion.source_y; dz = p->motion.dest_z - p->motion.source_z; if (speed == 0 || (dx == 0 && dy == 0 && dz == 0)) p->motion.increment = 1.0; else { distance = GetLongSqrt(dx * dx + dy * dy + dz * dz) / FINENESS; p->motion.increment = ((float) speed) / 1000.0 / distance; } p->motion.x = p->motion.source_x; p->motion.y = p->motion.source_y; p->motion.z = p->motion.source_z; p->motion.progress = 0.0; // Set projectile angle p->angle = intATan2(dy, dx) & NUMDEGREES_MASK; p->flags = flags; p->reserved = reserved; current_room.projectiles = list_add_item(current_room.projectiles, p); }
/* * RadiusProjectileAdd: Starts a new radius projectile on its way. * Projectile goes from source object to the range limit of the spell. */ void RadiusProjectileAdd(Projectile *p, ID source_obj, BYTE speed, WORD flags, WORD reserved, BYTE range, BYTE number) { float distance, destx, desty, radangle, fRange; int dx, dy, dz, destz; room_contents_node *s; fRange = range; float initangle = 0.0; // If animation off, don't bother with projectiles. if (!config.animate) return; for (int i=1; i <= number; i++) { Projectile *q = (Projectile *) ZeroSafeMalloc(sizeof(Projectile)); q->icon_res = p->icon_res; q->translation = p->translation; q->animate = p->animate; q->dLighting = p->dLighting; // Set source coordinates based on object location s = GetRoomObjectById(source_obj); q->motion.source_x = s->motion.x; q->motion.source_y = s->motion.y; q->motion.source_z = s->motion.z; //GetPointFloor(s->motion.x, s->motion.y); #if 0 if (source_obj == player.id) q->motion.source_z += PlayerGetHeightOffset() / (FINENESS * 2); else q->motion.source_z += s->obj.boundingHeight / (FINENESS * 2); #endif /* We're launching projectiles in a circle, so we need to determine which angle we need to shoot this projectile, and the destination. */ radangle = (initangle*3.14159)/180.0; destx = s->motion.x + ((fRange*1000.0) * cos(radangle)); desty = s->motion.y + ((fRange*1000.0) * sin(radangle)); destz = s->motion.z; #if 0 destz += PlayerGetHeightOffset() / (FINENESS * 2); #endif q->motion.dest_x = (destx); q->motion.dest_y = (desty); q->motion.dest_z = destz; //GetPointFloor(s->motion.x + range, s->motion.y + range); // See how far we should move per frame dx = q->motion.dest_x - q->motion.source_x; dy = q->motion.dest_y - q->motion.source_y; dz = q->motion.dest_z - q->motion.source_z; if (speed == 0 || (dx == 0 && dy == 0 && dz == 0)) q->motion.increment = 1.0; else { distance = GetLongSqrt(dx * dx + dy * dy + dz * dz) / FINENESS; q->motion.increment = ((float) speed) / 1000.0 / distance; } q->motion.x = q->motion.source_x; q->motion.y = q->motion.source_y; q->motion.z = q->motion.source_z; q->motion.progress = 0.0; // Set projectile angle. q->angle = intATan2(dy, dx) & NUMDEGREES_MASK; q->flags = flags; q->reserved = reserved; current_room.projectiles = list_add_item(current_room.projectiles, q); // Set next angle. initangle = initangle + 360.0/number; } SafeFree(p); }
/* * InterfaceAction: User wants to perform given action. Return True iff * action should be passed along for further processing. */ Bool InterfaceAction(int action, void *action_data) { POINT mouse; AREA a; room_contents_node *r; static int lastRestWarning = 0; if ((pinfo.resting || cinfo->effects->paralyzed) && (IsMoveAction(action) || IsAttackAction(action))) { // debug(("Can't do while resting\n")); return False; } switch (action) { case A_TARGETCLEAR: case A_TARGETSELF: case A_TARGETNEXT: case A_TARGETPREVIOUS: case A_ATTACK: UserAreaRedraw(); return True; break; case A_FORWARDFAST: // If too tired, don't run if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_FORWARD, NULL); return False; } break; case A_BACKWARDFAST: if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_BACKWARD, NULL); return False; } break; case A_SLIDELEFTFAST: if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_SLIDELEFT, NULL); return False; } break; case A_SLIDERIGHTFAST: if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_SLIDERIGHT, NULL); return False; } break; case A_SLIDELEFTFORWARDFAST: if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_SLIDELEFTFORWARD, NULL); return False; } break; case A_SLIDELEFTBACKWARDFAST: if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_SLIDELEFTBACKWARD, NULL); return False; } break; case A_SLIDERIGHTFORWARDFAST: if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_SLIDERIGHTFORWARD, NULL); return False; } break; case A_SLIDERIGHTBACKWARDFAST: if (pinfo.vigor < MIN_VIGOR) { PerformAction(A_SLIDERIGHTBACKWARD, NULL); return False; } break; case A_CAST: UserCastSpell(); return False; case A_CASTSPELL: // action_data is pointer to spell if (GetPlayer()->viewID && (GetPlayer()->viewID != GetPlayer()->id)) { if (!(GetPlayer()->viewFlags & REMOTE_VIEW_CAST)) { GameMessage(GetString(hInst, IDS_SPELLPARALYZED)); return False; } } if (cinfo->effects->paralyzed) { GameMessage(GetString(hInst, IDS_SPELLPARALYZED)); return False; } if (pinfo.resting) { GameMessage(GetString(hInst, IDS_SPELLRESTING)); return False; } SpellCast((spell *) action_data); return False; case A_GO: if (pinfo.resting) return False; break; case A_ENDDRAG: // action_data is ID of object being dragged // See if user dragged object to inventory InventoryGetArea(&a); GetCursorPos(&mouse); ScreenToClient(cinfo->hMain, &mouse); if (!IsInArea(&a, mouse.x, mouse.y)) break; r = GetRoomObjectById((ID) action_data); if (r == NULL) break; // If a non-gettable container, try to get contents if ((r->obj.flags & OF_CONTAINER) && !(r->obj.flags & OF_GETTABLE)) RequestObjectContents((ID) action_data); else RequestPickup((ID) action_data); break; case A_TABFWD: return InterfaceTab((int) action_data, True); case A_TABBACK: return InterfaceTab((int) action_data, False); } return True; }