/** * @brief Trigger to open the door we are standing in front of it * @sa CL_DoorOpen * @sa LE_CloseOpen * @sa CL_ActorDoorAction * @sa AI_CheckUsingDoor */ static bool Touch_DoorTrigger (edict_t *self, edict_t *activator) { if (self->owner && self->owner->inuse) { if (G_IsAI(activator)) { /* let the ai interact with the door */ if (self->flags & FL_GROUPSLAVE) self = self->groupMaster; if (AI_CheckUsingDoor(activator, self->owner)) G_ActorUseDoor(activator, self->owner); /* we don't want the client action stuff to be send for ai actors */ return false; } else { /* prepare for client action */ G_ActorSetClientAction(activator, self->owner); return true; } } return false; }
/** * @brief The client sent us a message that he did something. We now execute the related function(s) and notify him if necessary. * @param[in] player The player to execute the action for (the actor belongs to this player) * @note a client action will also send the server side edict number to determine the actor */ int G_ClientAction (player_t * player) { player_action_t action; int num; pos3_t pos; int i; fireDefIndex_t firemode; int from, fx, fy, to, tx, ty; actorHands_t hand; int fmIdx, objIdx; int resCrouch, resShot; edict_t *ent; const char *format; /* read the header */ action = (player_action_t)gi.ReadByte(); num = gi.ReadShort(); ent = G_EdictsGetByNum(num); if (ent == NULL) return action; format = pa_format[action]; switch (action) { case PA_NULL: /* do nothing on a null action */ break; case PA_TURN: gi.ReadFormat(format, &i); G_ClientTurn(player, ent, (dvec_t) i); break; case PA_MOVE: gi.ReadFormat(format, &pos); G_ClientMove(player, player->pers.team, ent, pos); break; case PA_STATE: gi.ReadFormat(format, &i); G_ClientStateChange(player, ent, i, true); break; case PA_SHOOT: gi.ReadFormat(format, &pos, &i, &firemode, &from); G_ClientShoot(player, ent, pos, i, firemode, NULL, true, from); break; case PA_INVMOVE: gi.ReadFormat(format, &from, &fx, &fy, &to, &tx, &ty); if (from < 0 || from >= gi.csi->numIDs || to < 0 || to >= gi.csi->numIDs) { gi.DPrintf("G_ClientAction: PA_INVMOVE Container index out of range. (from: %i, to: %i)\n", from, to); } else { const invDef_t *fromPtr = INVDEF(from); const invDef_t *toPtr = INVDEF(to); invList_t *fromItem = INVSH_SearchInInventory(&ent->chr.i, fromPtr, fx, fy); if (fromItem) G_ActorInvMove(ent, fromPtr, fromItem, toPtr, tx, ty, true); } break; case PA_USE: if (ent->clientAction) { edict_t *actionEnt; /* read the door the client wants to open */ gi.ReadFormat(format, &i); /* get the door edict */ actionEnt = G_EdictsGetByNum(i); /* maybe the door is no longer 'alive' because it was destroyed */ if (actionEnt && ent->clientAction == actionEnt) { if (G_IsDoor(actionEnt)) { G_ActorUseDoor(ent, actionEnt); } } } break; case PA_REACT_SELECT: gi.ReadFormat(format, &hand, &fmIdx, &objIdx); G_ReactionFireSettingsUpdate(ent, fmIdx, hand, INVSH_GetItemByIDX(objIdx)); break; case PA_RESERVE_STATE: gi.ReadFormat(format, &resShot, &resCrouch); G_ActorReserveTUs(ent, ent->chr.reservedTus.reaction, resShot, resCrouch); break; default: gi.Error("G_ClientAction: Unknown action!\n"); } return action; }