#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define fi first
#define se second
#define pb push_back
#define MAX 200200

struct segtree
{
    int n;
    vector<ll> st;
    segtree(int _n)
    {
        n = _n;
        st.resize(n*4,0);
    }

    void update(int id, int l, int r, int pos, int val)
    {
        if(l == r){
            st[id] += val;
        }else{
            int m = (l+r)>>1;
            if(pos <= m) update(id<<1,l,m,pos,val);
            else update(id<<1|1,m+1,r,pos,val);
            st[id] = st[id<<1] + st[id<<1|1];
        }
    }

    ll get(int id, int l, int r, int u, int v)
    {
        if(r < u || v < l) return 0;
        if(u <= l && r <= v) return st[id];
        int m = (l+r)>>1;
        return get(id<<1,l,m,u,v) + get(id<<1|1,m+1,r,u,v);
    }
};

int n,m,q,root;
vector<pair<int,int> > adjj[MAX];
ll d[MAX];
int par[MAX], depth[MAX], sz[MAX], head[MAX], pos[MAX];
int cnt = 0;
vector<int> adj[MAX];

void nhap()
{
    memset(d,0x3f,sizeof(d));
    cin >> n >> m >> root >> q;
    for(int i = 1; i<=m; i++){
        int a,b,c; cin >> a >> b >> c;
        adjj[a].pb({b,c});
        adjj[b].pb({a,c});
    }
}

void dijkstra()
{
    d[root] = 0;
    priority_queue<pair<ll,int>, vector<pair<ll,int> >, greater<pair<ll,int> > > pq;
    pq.push({0,root});
    while(!pq.empty()){
        pair<ll,int> top = pq.top(); pq.pop();
        if(top.fi != d[top.se]) continue;
        for(pair<int,int> u : adjj[top.se]){
            if(d[u.fi] > top.fi + u.se){
                d[u.fi] = top.fi + u.se;
                pq.push({d[u.fi], u.fi});
            }
        }
    }
}

void pre_compute()
{
    for(int i = 1; i<=n; i++) if(i != root){
        int cur = n+1;
        for(pair<int,int> u : adjj[i]) if(d[u.fi] + u.se == d[i]){
            cur = min(cur, u.fi);
        }
        if(cur != n+1){
            adj[cur].pb(i);
            adj[i].pb(cur);
        }
    }
    par[root] = 0;
    depth[root] = 0;
}

void dfs(int v)
{
    int ind = -1;
    sz[v] = 1;
    for(int i = 0; i<adj[v].size(); i++) if(adj[v][i] != par[v]){
        int u = adj[v][i];
        par[u] = v;
        depth[u] = depth[v]  +1;
        dfs(u);
        sz[v] += sz[u];
        if(ind == -1 || sz[u] > sz[adj[v][ind]]) ind = i;
    }
    if(ind != -1 && ind != 0) swap(adj[v][0], adj[v][ind]);
}

void decompose(int v, int h)
{
    head[v] = h;
    pos[v] = ++cnt;
    for(int u : adj[v]) if(u != par[v]){
        if(u == adj[v][0]) decompose(u,h);
        else decompose(u,u);
    }
}

void process()
{
    segtree st(n);
    while(q--){
        int t; cin >> t;
        if(t == 1){
            int u, val; cin >> u >> val;
            st.update(1,1,n,pos[u],val);
        }else{
            int u, v; cin >> u >> v;
            ll ans = 0;
            while(head[u] != head[v]){
                if(depth[head[u]] < depth[head[v]]) swap(u,v);
                ans += st.get(1,1,n,pos[head[u]], pos[u]);
                u = par[head[u]];
            }
            if(depth[u] > depth[v]) swap(u,v);
            ans += st.get(1,1,n,pos[u], pos[v]);
            cout << ans << '\n';
        }
    }
}

 main()
{
    ios_base::sync_with_stdio(0); cin.tie(0);
    nhap();
    dijkstra();
    pre_compute();
    dfs(root);
    decompose(root,root);
    process();
    return 0;
}
