__( 'Buddy', 'buddy' ), 'species' => 'default', 'hunger' => 80, 'happiness' => 80, 'health' => 90, 'energy' => 70, 'born_at' => time(), 'last_tick' => time(), ); } /** * Fetch the current user's Buddy state, falling back to defaults and * persisting them on first read so the pet has a "birthday" timestamp. * * @param int $user_id Optional. Defaults to current user. * @return array { name, species, hunger, happiness, health, energy, born_at, last_tick } */ function buddy_get_state( $user_id = 0 ) { $user_id = $user_id ? (int) $user_id : get_current_user_id(); if ( ! $user_id ) { return buddy_default_state(); } $state = get_user_meta( $user_id, BUDDY_META_KEY, true ); if ( ! is_array( $state ) || empty( $state ) ) { $state = buddy_default_state(); update_user_meta( $user_id, BUDDY_META_KEY, $state ); } // Merge against defaults so newly-added keys appear with sensible // values for users adopted under earlier versions. return array_merge( buddy_default_state(), $state ); } /** * Persist a partial state update for the current user. Unknown keys * are silently dropped; values are clamped to valid ranges. * * @param array $patch Keys: name (str), species (str), hunger/happiness/health/energy (int 0–100). * @return array The full updated state. */ function buddy_update_state( array $patch, $user_id = 0 ) { $user_id = $user_id ? (int) $user_id : get_current_user_id(); if ( ! $user_id ) { return buddy_default_state(); } $state = buddy_get_state( $user_id ); $stat_keys = array( 'hunger', 'happiness', 'health', 'energy' ); foreach ( $stat_keys as $k ) { if ( array_key_exists( $k, $patch ) ) { $state[ $k ] = max( 0, min( 100, (int) $patch[ $k ] ) ); } } if ( array_key_exists( 'name', $patch ) ) { $name = sanitize_text_field( (string) $patch['name'] ); if ( $name !== '' && mb_strlen( $name ) <= 32 ) { $state['name'] = $name; } } if ( array_key_exists( 'species', $patch ) ) { $allowed_species = array( 'default' ); // Phase D will widen this. $sp = sanitize_key( (string) $patch['species'] ); if ( in_array( $sp, $allowed_species, true ) ) { $state['species'] = $sp; } } update_user_meta( $user_id, BUDDY_META_KEY, $state ); return $state; } /** * Average of the four stats — used as a single "mood" indicator for * the dashboard widget. Returns 0–100. */ function buddy_overall_mood( array $state ) { $sum = (int) $state['hunger'] + (int) $state['happiness'] + (int) $state['health'] + (int) $state['energy']; return (int) round( $sum / 4 ); } /** * Pick a one-word emoji / status label based on overall mood. Pure * cosmetic, used in the dashboard widget header. */ function buddy_mood_label( $mood_score ) { if ( $mood_score >= 80 ) { return array( 'label' => __( 'Thriving', 'buddy' ), 'tone' => 'happy' ); } if ( $mood_score >= 60 ) { return array( 'label' => __( 'Content', 'buddy' ), 'tone' => 'happy' ); } if ( $mood_score >= 40 ) { return array( 'label' => __( 'Okay', 'buddy' ), 'tone' => 'neutral' ); } if ( $mood_score >= 20 ) { return array( 'label' => __( 'Hungry', 'buddy' ), 'tone' => 'sad' ); } return array( 'label' => __( 'Distressed', 'buddy' ), 'tone' => 'sad' ); }