Beispiel #1
0
/**
 * Substitute placeholders in a command string. Placeholders consist of two characters,
 * the first being a %. Use %% to output a plain % character.
 *
 * - <code>%i</code>: id member of the event
 * - <code>%p</code>: (symbolic events only) local player number
 *
 * @param command  Original command string with the placeholders.
 * @param event    Event data.
 * @param eb       Binding data.
 * @param out      String with placeholders replaced.
 */
static void B_SubstituteInCommand(char const *command, ddevent_t const *event,
                                  evbinding_t *eb, ddstring_t *out)
{
    const char* ptr = command;

    for(; *ptr; ptr++)
    {
        if(*ptr == '%')
        {
            // Escape.
            ptr++;

            // Must have another character in the placeholder.
            if(!*ptr) break;

            if(*ptr == 'i')
            {
                int id = 0;
                switch(event->type)
                {
                    case E_TOGGLE:
                        id = event->toggle.id;
                        break;

                    case E_AXIS:
                        id = event->axis.id;
                        break;

                    case E_ANGLE:
                        id = event->angle.id;
                        break;

                    case E_SYMBOLIC:
                        id = event->symbolic.id;
                        break;

                    default:
                        break;
                }
                Str_Appendf(out, "%i", id);
            }
            else if(*ptr == 'p')
            {
                int id = 0;
                if(event->type == E_SYMBOLIC)
                {
                    id = P_ConsoleToLocal(event->symbolic.id);
                }
                Str_Appendf(out, "%i", id);
            }
            else if(*ptr == '%')
            {
                Str_AppendChar(out, *ptr);
            }
            continue;
        }

        Str_AppendChar(out, *ptr);
    }
}
Beispiel #2
0
void B_AppendAxisPositionToString(ebstate_t state, float pos, ddstring_t* str)
{
    if(state == EBAXIS_WITHIN)
        Str_Appendf(str, "-within%g", pos);
    else if(state == EBAXIS_BEYOND)
        Str_Appendf(str, "-beyond%g", pos);
    else if(state == EBAXIS_BEYOND_POSITIVE)
        Str_Appendf(str, "-pos%g", pos);
    else
        Str_Appendf(str, "-neg%g", -pos);
}
Beispiel #3
0
void B_AppendDeviceDescToString(uint device, ddeventtype_t type, int id, ddstring_t* str)
{
    inputdev_t* dev = I_GetDevice(device, false);
    const char* name;

    if(type != E_SYMBOLIC)
    {
        // Name of the device.
        Str_Append(str, dev->name);
        Str_Append(str, "-");
    }

    switch(type)
    {
    case E_TOGGLE:
        if(dev->keys[id].name)
        {
            Str_Append(str, dev->keys[id].name);
        }
        else if(device == IDEV_KEYBOARD)
        {
            name = B_ShortNameForKey(id);
            if(name)
                Str_Append(str, name);
            else
                Str_Appendf(str, "code%03i", id);
        }
        else
            Str_Appendf(str, "button%i",id + 1);
        break;

    case E_AXIS:
        Str_Append(str, dev->axes[id].name);
        break;

    case E_ANGLE:
        Str_Appendf(str, "hat%i", id + 1);
        break;

    case E_SYMBOLIC:
        Str_Append(str, "sym");
        break;

    default:
        Con_Error("B_AppendDeviceDescToString: Invalid value, type = %i.",
                  (int) type);
        break;
    }
}
Beispiel #4
0
/**
 * @param ev  Event.
 * @param str  The event in textual format is appended here.
 */
void B_AppendEventToString(const ddevent_t* ev, ddstring_t* str)
{
    B_AppendDeviceDescToString(ev->device, ev->type,
                               ev->type == E_TOGGLE? ev->toggle.id :
                               ev->type == E_AXIS? ev->axis.id :
                               ev->type == E_ANGLE? ev->angle.id :
                               ev->type == E_SYMBOLIC? ev->symbolic.id :
                               0, str);

    switch(ev->type)
    {
    case E_TOGGLE:
        B_AppendToggleStateToString(ev->toggle.state == ETOG_DOWN? EBTOG_DOWN :
                                    ev->toggle.state == ETOG_UP? EBTOG_UP :
                                    EBTOG_REPEAT, str);
        break;

    case E_AXIS:
        B_AppendAxisPositionToString(ev->axis.pos >= 0? EBAXIS_BEYOND_POSITIVE :
                                     EBAXIS_BEYOND_NEGATIVE, ev->axis.pos, str);
        break;

    case E_ANGLE:
        B_AppendAnglePositionToString(ev->angle.pos, str);
        break;

    case E_SYMBOLIC:
        Str_Appendf(str, "-%s", ev->symbolic.name);
        break;

    case E_FOCUS:
        break;
    }
}
Beispiel #5
0
void B_AppendAnglePositionToString(float pos, ddstring_t* str)
{
    if(pos < 0)
        Str_Append(str, "-center");
    else
        Str_Appendf(str, "-angle%g", pos);
}
Beispiel #6
0
/**
 * Does the opposite of the B_Parse* methods for event descriptor, including the
 * state conditions.
 */
void B_EventBindingToString(const evbinding_t* eb, ddstring_t* str)
{
    int         i;

    Str_Clear(str);
    B_AppendDeviceDescToString(eb->device, eb->type, eb->id, str);

    if(eb->type == E_TOGGLE)
    {
        B_AppendToggleStateToString(eb->state, str);
    }
    else if(eb->type == E_AXIS)
    {
        B_AppendAxisPositionToString(eb->state, eb->pos, str);
    }
    else if(eb->type == E_ANGLE)
    {
        B_AppendAnglePositionToString(eb->pos, str);
    }
    else if(eb->type == E_SYMBOLIC)
    {
        Str_Appendf(str, "-%s", eb->symbolicName);
    }

    // Append any state conditions.
    for(i = 0; i < eb->numConds; ++i)
    {
        Str_Append(str, " + ");
        B_AppendConditionToString(&eb->conds[i], str);
    }
}
Beispiel #7
0
void P_SetYellowMessage(player_t* pl, int flags, const char* msg)
{
#define YELLOW_FMT      "{r=1;g=0.7;b=0.3;}"
#define YELLOW_FMT_LEN  18

    size_t len;
    AutoStr* buf;

    if(!msg || !msg[0]) return;
    len = strlen(msg);

    buf = AutoStr_NewStd();
    Str_Reserve(buf, YELLOW_FMT_LEN + len+1);
    Str_Set(buf, YELLOW_FMT);
    Str_Appendf(buf, "%s", msg);

    ST_LogPost(pl - players, flags, Str_Text(buf));

    if(pl == &players[CONSOLEPLAYER] && cfg.echoMsg)
        Con_FPrintf(CPF_CYAN, "%s\n", msg);

    // Servers are responsible for sending these messages to the clients.
    /// @todo We shouldn't need to send the format string along with every
    /// important game message. Instead flag a bit in the packet and then
    /// reconstruct on the other end.
    NetSv_SendMessage(pl - players, Str_Text(buf));

#undef YELLOW_FMT
}
Beispiel #8
0
/**
 * Open a demo file and begin recording.
 * Returns false if the recording can't be begun.
 */
boolean Demo_BeginRecording(const char* fileName, int plrNum)
{
    DENG_UNUSED(fileName);
    DENG_UNUSED(plrNum);
    return false;

#if 0
    client_t* cl = &clients[plrNum];
    player_t* plr = &ddPlayers[plrNum];
    ddstring_t buf;

    // Is a demo already being recorded for this client?
    if(cl->recording || playback || (isDedicated && !plrNum) || !plr->shared.inGame)
        return false;

    // Compose the real file name.
    Str_InitStd(&buf);
    Str_Appendf(&buf, "%s%s", demoPath, fileName);
    F_ExpandBasePath(&buf, &buf);
    F_ToNativeSlashes(&buf, &buf);

    // Open the demo file.
    cl->demo = lzOpen(Str_Text(&buf), "wp");
    Str_Free(&buf);
    if(!cl->demo)
    {
        return false; // Couldn't open it!
    }

    cl->recording = true;
    cl->recordPaused = false;
    writeInfo[plrNum].first = true;
    writeInfo[plrNum].canwrite = false;
    writeInfo[plrNum].cameratimer = 0;
    writeInfo[plrNum].fov = -1; // Must be written in the first packet.

    if(isServer)
    {
        // Playing demos alters gametic. This'll make sure we're going to
        // get updates.
        clients[0].lastTransmit = -1;
        // Servers need to send a handshake packet.
        // It only needs to recorded in the demo file, though.
        allowSending = false;
        Sv_Handshake(plrNum, false);
        // Enable sending to network.
        allowSending = true;
    }
    else
    {
        // Clients need a Handshake packet.
        // Request a new one from the server.
        Cl_SendHello();
    }

    // The operation is a success.
    return true;
#endif
}
Beispiel #9
0
void B_AppendConditionToString(const statecondition_t* cond, ddstring_t* str)
{
    if(cond->type == SCT_STATE)
    {
        if(cond->flags.multiplayer)
        {
            Str_Append(str, "multiplayer");
        }
    }
    else if(cond->type == SCT_MODIFIER_STATE)
    {
        Str_Appendf(str, "modifier-%i", cond->id - CTL_MODIFIER_1 + 1);
    }
    else
    {
        B_AppendDeviceDescToString(cond->device,
                                   cond->type == SCT_TOGGLE_STATE? E_TOGGLE :
                                   cond->type == SCT_AXIS_BEYOND? E_AXIS : E_ANGLE,
                                   cond->id, str);
    }

    if(cond->type == SCT_TOGGLE_STATE || cond->type == SCT_MODIFIER_STATE)
    {
        B_AppendToggleStateToString(cond->state, str);
    }
    else if(cond->type == SCT_AXIS_BEYOND)
    {
        B_AppendAxisPositionToString(cond->state, cond->pos, str);
    }
    else if(cond->type == SCT_ANGLE_AT)
    {
        B_AppendAnglePositionToString(cond->pos, str);
    }

    // Flags.
    if(cond->flags.negate)
    {
        Str_Append(str, "-not");
    }
}
Beispiel #10
0
static Uri *readTextureUrn(Reader *reader, char const *schemeName)
{
    DENG_ASSERT(reader && schemeName);
    return Uri_NewWithPath2(Str_Text(Str_Appendf(AutoStr_NewStd(), "urn:%s:%i", schemeName, Reader_ReadInt16(svReader))), RC_NULL);
}
Beispiel #11
0
/// @note Derived from Qt's QByteArray q_toPercentEncoding
ddstring_t *Str_PercentEncode2(ddstring_t *str, char const *excludeChars, char const *includeChars)
{
    dd_bool didEncode = false;
    int i, span, begin, len;
    ddstring_t buf;

    DENG_ASSERT(str);
    if(!str) return 0;

    if(Str_IsEmpty(str)) return str;

    len = Str_Length(str);
    begin = span = 0;
    for(i = 0; i < len; ++i)
    {
        char ch = str->str[i];

        // Are we encoding this?
        if(((ch >= 0x61 && ch <= 0x7A) // ALPHA
            || (ch >= 0x41 && ch <= 0x5A) // ALPHA
            || (ch >= 0x30 && ch <= 0x39) // DIGIT
            || ch == 0x2D // -
            || ch == 0x2E // .
            || ch == 0x5F // _
            || ch == 0x7E // ~
            || (excludeChars && strchr(excludeChars, ch)))
           && !(includeChars && strchr(includeChars, ch)))
        {
            // Not an encodeable. Span grows.
            span++;
        }
        else
        {
            // Found an encodeable.
            if(!didEncode)
            {
                Str_InitStd(&buf);
                Str_Reserve(&buf, len*3); // Worst case.
                didEncode = true;
            }

            Str_PartAppend(&buf, str->str, begin, span);
            Str_Appendf(&buf, "%%%X", (uint)ch);

            // Start a new span.
            begin += span + 1;
            span = 0;
        }
    }

    if(didEncode)
    {
        // Copy anything remaining.
        if(span)
        {
            Str_PartAppend(&buf, str->str, begin, span);
        }

        Str_Set(str, Str_Text(&buf));
        Str_Free(&buf);
    }

    return str;
}
Beispiel #12
0
void FI_StackExecuteWithId(const char* scriptSrc, int flags, finale_mode_t mode, const char* defId)
{
    fi_state_t* s, *prevTopScript;
    gamestate_t prevGamestate;
    ddstring_t setupCmds;
    finaleid_t finaleId;
    int i, fontIdx;

    if(!finaleStackInited) Con_Error("FI_StackExecute: Not initialized yet!");

    // Should we ignore this?
    if(defId && stackHasDefId(defId))
    {
        Con_Message("There already is a finale running with ID \"%s\"; won't execute again.", defId);
        return;
    }

    prevGamestate = G_GameState();
    prevTopScript = stackTop();

    // Configure the predefined fonts.
    Str_Init(&setupCmds);
    fontIdx = 1;
    Str_Appendf(&setupCmds,   "prefont %i %s", fontIdx++, "a");
    Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "b");
    Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "status");
#if __JDOOM__
    Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "index");
#endif
#if __JDOOM__ || __JDOOM64__
    Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "small");
#endif
#if __JHERETIC__ || __JHEXEN__
    Str_Appendf(&setupCmds, "\nprefont %i %s", fontIdx++, "smallin");
#endif

    // Configure the predefined colors.
#if __JDOOM__
    Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB[CR],  defFontRGB[CG],  defFontRGB[CB]);
    Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]);
    Str_Appendf(&setupCmds, "\nprecolor 3 %f %f %f\n", defFontRGB3[CR], defFontRGB3[CG], defFontRGB3[CB]);
    i = 4;
#elif __JHERETIC__
    Str_Appendf(&setupCmds, "\nprecolor 3 %f %f %f\n", defFontRGB[CR],  defFontRGB[CG],  defFontRGB[CB]);
    Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]);
    Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB3[CR], defFontRGB3[CG], defFontRGB3[CB]);
    i = 4;
#elif __JHEXEN__
    Str_Appendf(&setupCmds, "\nprecolor 3 %f %f %f\n", defFontRGB[CR],  defFontRGB[CG],  defFontRGB[CB]);
    Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]);
    Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB3[CR], defFontRGB3[CG], defFontRGB3[CB]);
    i = 4;
#elif __JDOOM64__
    Str_Appendf(&setupCmds, "\nprecolor 2 %f %f %f\n", defFontRGB[CR],  defFontRGB[CG],  defFontRGB[CB]);
    Str_Appendf(&setupCmds, "\nprecolor 1 %f %f %f\n", defFontRGB2[CR], defFontRGB2[CG], defFontRGB2[CB]);
    i = 3;
#else
    i = 0;
#endif
    // Set the rest to white.
    for(; i <= FIPAGE_NUM_PREDEFINED_COLORS; ++i)
    {
        Str_Appendf(&setupCmds, "\nprecolor %i 1 1 1\n", i);
    }

    finaleId = FI_Execute2(scriptSrc, flags, Str_Text(&setupCmds));
    Str_Free(&setupCmds);
    if(finaleId == 0)
        return;

    if(mode != FIMODE_OVERLAY)
    {
        G_ChangeGameState(GS_INFINE);
    }

    // Only the top-most script can be "active".
    if(prevTopScript)
    {
        FI_ScriptSuspend(prevTopScript->finaleId);
    }

    s = stackPush(finaleId, mode, prevGamestate, defId);

    // Do we need to transmit the state conditions to clients?
    if(IS_SERVER && !(flags & FF_LOCAL))
    {
        NetSv_SendFinaleState(s);
    }
}