scalePhone - an iFruit Phone framework

Thank you a lot! :heart_eyes:

    function CreateHomePage()
        --TriggerEvent('scalePhone.BuildHomepageApp', appID, appType, appName, appIcon, appNotificationInt--[[only working on homepage apps]], openEvent, backEvent, data)
        TriggerEvent('scalePhone.BuildHomepageApp', 1, "contacts", "Contacts", 5, 0, "scalePhone.app_contacts", "scalePhone.GoToHomepage", {})
        TriggerEvent('scalePhone.BuildHomepageApp', 2, "messagesList", "Messages List", 2, 0, "scalePhone.app_messagesList", "scalePhone.GoToHomepage", {})
        TriggerEvent('scalePhone.BuildHomepageApp', 3, "emailList", "Email List", 4, 0, "scalePhone.app_emailList", "scalePhone.GoToHomepage", {})
        TriggerEvent('scalePhone.BuildHomepageApp', 4, "missionStatsView", "Mission Stats View", 6, 0, "scalePhone.app_missionStatsView", "scalePhone.GoToHomepage", {})
        TriggerEvent('scalePhone.BuildThemeSettings', 8) 
        TriggerEvent('scalePhone.BuildSnapmatic', 9)
    end

    function LoadContacts()
        --====================================================================================================================================================================-- 
        local data = {name = "Mike", pic = "CHAR_MP_SNITCH", isBot = false, event = "scalePhone.call_mike", eventParams = {data1 = "MIKE"}}
        TriggerEvent('scalePhone.BuildAppButton', 1, data, false, -1)
        --====================================================================================================================================================================--
        data = {name = "Taxi", pic = "CHAR_TAXI", isBot = false, event = "scalePhone.call_taxi", eventParams = {data1 = "TAXI"}}
        TriggerEvent('scalePhone.BuildAppButton', 1, data, false, -1)
        --====================================================================================================================================================================--
        data = {name = "Mechanic", pic = "CHAR_MECHANIC", isBot = false, event = "scalePhone.call_mechanic", eventParams = {data1 = "MECHANIC"}}
        TriggerEvent('scalePhone.BuildAppButton', 1, data, false, -1)
        --====================================================================================================================================================================--
        data = {name = "Ashley", pic = "CHAR_ASHLEY", isBot = false, event = "scalePhone.call_ashley", eventParams = {data1 = "ASHLEY"}}
        TriggerEvent('scalePhone.BuildAppButton', 1, data, false, -1)
        --====================================================================================================================================================================--
    end

image

then…
what AppID should i give to the callscreens… ?
how does the contact start the right callscreen…

if AppID = 1 will bypass the contact list… and unique like here (7) nothing happen, or i just dont get the events thing… with the actual wiki.

    function LoadCallscreens()
        local data = {contact = "Mike", pic = "CHAR_MP_SNITCH", status = "Calling.."}
        TriggerEvent('scalePhone.BuildApp', 7, "callscreen", "Mike", 0, 0, "scalePhone.call_mike", "scalePhone.app_contacts", data)
        TriggerEvent('scalePhone.BuildCallscreenView', data, 7)
    end

Phone is pretty superb… love it.

1 Like

You will first need a “callscreen” app.
For example, you can create the callscreen “app” like this:

TriggerEvent('scalePhone.BuildApp', 7--[[appID]], "callscreen", "Call"--[[app name. Not shown]], 0, 0, openEvent, 'scalePhone.GoBackApp'--[[prebuilt event, it will "go back" to the last app, or a different appID, provided in the data array as "backApp"]], {backApp = 1}--[[data array]])

After that, when building the contacts, you can use the ‘event’ and ‘eventParams’ data to create some sort of flow for the call screen. This is how I would do it:

local data = {name = "Ashley", pic = "CHAR_ASHLEY", isBot = false, event = "phone.OpenCallscreen", eventParams = {{name = "Ashley", pic = "CHAR_ASHLEY", isBot = false}}
        TriggerEvent('scalePhone.BuildAppButton', 1, data, false, -1)

AddEventHandler('phone.OpenCallscreen', function(data)
    TriggerEvent('scalePhone.BuildCallscreenView', {backApp = 1, contact = data.name, pic = data.pic, status = "CALLING"}, 7)
    TriggerEvent('scalePhone.OpenApp',7, false)
    TriggerServerEvent('phone.sv.SendCall', data.name, data.pic, data.isBot) --this is where you send the server that you want to call someone, and the name.
end)

Notice how I don’t use the eventParams variable as one param, but as an array, with whatever information I want. You can add whatever you want there. For example you can add a playerID variable in that array, which will be equivalent with the player’s server ID.

The framework itself will leave that variable in peace, but you can use it on the events that you trigger!

You can add whatever appID you want. The idea is to use the button’s event and eventParams to start the call logic.

I know it’s a bit convoluted and “complex” in a unnecessary way. As I said, I’m still working on a good wiki, and a standalone “full phone”. Hopefully, example code will make it more easy to understand.

2 Likes

Thank you very much for taking the time to explain more… i was looking at it the wrong way and my brain got stuck in an infinit loop… :slight_smile:

1 Like

I know. I didn’t put that much effort in a proper “architecture”…actually most of it was made while still figuring out the scaleforms.

You can think of the events kinda like modifying a config file.
If you look at the event handlers in cl_phone_events.lua, you will see that that’s pretty much what most of them do. They are modifying the apps array in cl_phone_handle.lua, adding new apps, buttons, views, etc. Then, every app has it’s own handling event for the phone controls.

For example, this is how the “contacts” apps handle input:

AddEventHandler('scalePhone.HandleInput.contacts', function(input)
    if input == "left" then
        CellCamMoveFinger(4)
        Scaleform.CallFunction(phoneScaleform, false, "SET_INPUT_EVENT", 4)
    elseif input == 'right' then
        CellCamMoveFinger(3)
        Scaleform.CallFunction(phoneScaleform, false, "SET_INPUT_EVENT", 2)
    elseif input == 'up' then
        CellCamMoveFinger(1)
        Scaleform.CallFunction(phoneScaleform, false, "SET_INPUT_EVENT", 1)
    elseif input == 'down' then
        CellCamMoveFinger(2)
        Scaleform.CallFunction(phoneScaleform, false, "SET_INPUT_EVENT", 3)
    elseif input == 'select' then
        CellCamMoveFinger(5)
        TriggerEvent(apps[appOpen].buttons[appSelectID].event, apps[appOpen].buttons[appSelectID].eventParams, false)
    elseif input == 'back' then
        CellCamMoveFinger(5)
        TriggerEvent(apps[appOpen].backEvent, apps[appOpen].data, false)
    end

    local ret = Scaleform.CallFunction(phoneScaleform, true, "GET_CURRENT_SELECTION")
    while true do
        if IsScaleformMovieMethodReturnValueReady(ret) then
            appSelectID = GetScaleformMovieMethodReturnValueInt(ret) --output
            break
        end
        Citizen.Wait(0)
    end
end)

left, right, up, down basically moves through the menu items, “selects” triggers the button “event”, with “eventParams” as it’s only param, and “back” triggers the “backEvent” of the app, with app’s “data” as param.

1 Like

i figured it out

From the wiki:

local contact = {name = "Contact Name", pic = "Mugshot or CHAR_PIC", isBot = false--[[or true]], event = "selectEvent", eventParams = {data1 = "any"--[[any data here]]}}
TriggerEvent('scalePhone.BuildAppButton', appID, contact, TopOrBottom--[[bool. true = set button at top of list, false = bottom]], -1)

appID needs to be the ID of a “contacts” app.

event = client event that will trigger whenever you select this button.
eventParams = the param that will be sent to the event.

for example:

AddEventHandler('selectEvent', function(data)
print(data.data1) --this will print "any" in client console
end)

Notice that we created a contact, with “selectEvent” event, and eventParams = {data1 = “any”}. That’s an array, and that’s how it was design / thought to be.

Whenever we select that contact (Enter by default), event “selectTrigger” will be… (wait for it) …triggered, like this:

TriggerEvent(contact.event, contact.eventParams)
1 Like

and these contacts are visibile only for me ?

for example i have this contact:

local data = {name = “Mecanic”, pic = “CHAR_MP_SNITCH”, isBot = false, event = “scalePhone.call_mecanic”, eventParams = {name = “Mecanic”, pic = “CHAR_MP_SNITCH”}}
TriggerEvent(‘scalePhone.BuildAppButton’, 1, data, false, -1)

this will be visible only for me right ?

Yes. Contacts, like any other app on the phone, is created client-side. If you want to only show that contact to a certain group of people, you might want to wrap the contact around an if statement:

if canSeeMecanic == true then --[[your condition here]]
    local data = {name = “Mecanic”, pic = “CHAR_MP_SNITCH”, isBot = false, event = “scalePhone.call_mecanic”, eventParams = {name = “Mecanic”, pic = “CHAR_MP_SNITCH”}}
    TriggerEvent(‘scalePhone.BuildAppButton’, 1, data, false, -1)
end

The glow the phone broadcast at night… also reflect in the sunglass… I am so happy with this release…

Now works like a phone with mumble? :open_mouth:

I mean…if you do the back-end, it can. I haven’t touched any voice-chat related things yet, I have other priorities now, but when I finish the phone for my server, I might release it as a standalone too.

1 Like

Please keep us updated about this, I’m in love with this phone! And I’ll be also happy to pay for a script like this, hard work need to be paid!

1 Like

Small update:

  • Callscreen:
    • Updated callscreen data tags. Now you need to add the following:

      {backApp = appID, contact = "Contact Name", pic = "CHAR_OR_MUGSHOT", status = "STATUS", canAnswer = false--[[if true, you can hit Enter, or you select button]], selectEvent = "event"--[[if canAnswer = true, this event will be triggered when you hit enter, or your select button]]}
      

      image

    • Callscreen no longer has the timer. That’s because during testing, I found that rebuilding the callscreen data multiple times will cause the status message to not actually get reset, but instead it will glitch and show all statuses for brief seconds. I commented the code, feel free to change it.

    • Whenever you switch the Sleep Mode setting in the settings menu, scalePhone.Event.SleepModeChanged will trigger, with the sleep mode status as args[1]

2 Likes

Estimate time to complete this phone? :heart_eyes::heart_eyes: looking forward, can’t wait :grin::grin:

Probably this weekend. I will update this resource, when it’s done. I want to be sure it’s available for everyone, not just for one framework.

1 Like

Oh god yes :heart_eyes::heart_eyes::heart_eyes::heart_eyes: thank you!

NEW! BREAKING! Want to see the phone in action? Try my App Pack!

  • People asked. I delivered. I made a resource that adds a bunch of apps to this phone.
    • You will need the framework active.
    • If you want to use the calling function you will need either pma-voice or mumble-voip(added, but not tested) (check sv_connections.lua)
  • Github link for the app pack: https://github.com/CritteRo/crit-phone

1 Like

Love uuuuuuuuuuuuuuuuuu will test soon as possibile and I will update in this post

1 Like

Donated for support the project, hope is enough, I will donate more soon as I can!

1 Like